diff --git a/examples/ui/custom.d b/examples/ui/custom.d index 33bb996..fa74848 100644 --- a/examples/ui/custom.d +++ b/examples/ui/custom.d @@ -1,21 +1,21 @@ -/// This example shows how to create custom UI items. +/// This example shows how to create a custom UI button. import parin; auto atlas = TextureId(); -bool myButton(IStr text) { +bool myButton(Rect area, IStr text) { // Create a button without drawing anything. - auto result = updateUiButton(Vec2(80, 30), text); + auto result = updateUiButton(area, text); // Draw the button above. if (isUiItemActive) { - drawTextureArea(atlas, Rect(uiItemSize), uiItemPoint, DrawOptions(gray3)); + drawTextureArea(atlas, Rect(area.size), area.position, DrawOptions(gray3)); } else if (isUiItemHot) { - drawTextureArea(atlas, Rect(uiItemSize), uiItemPoint, DrawOptions(gray2)); + drawTextureArea(atlas, Rect(area.size), area.position, DrawOptions(gray2)); } else { - drawTextureArea(atlas, Rect(uiItemSize), uiItemPoint, DrawOptions(gray1)); + drawTextureArea(atlas, Rect(area.size), area.position, DrawOptions(gray1)); } - drawUiText(uiItemSize, text, uiItemPoint, UiOptions(Alignment.left, 6)); + drawUiText(area, text, UiOptions(Alignment.left, 4)); return result; } @@ -27,9 +27,7 @@ void ready() { bool update(float dt) { prepareUi(); setUiFocus(0); - setUiStartPoint(Vec2(8)); - if (myButton("My Button 1")) println("Boom 1!"); - if (myButton("My Button 2")) println("Boom 2!"); + if (myButton(Rect(8, 8, 100, 25), "My Button")) println("Boom!"); return false; } diff --git a/examples/ui/field.d b/examples/ui/field.d index c78bd6e..883f911 100644 --- a/examples/ui/field.d +++ b/examples/ui/field.d @@ -2,8 +2,8 @@ import parin; -char[32] textBuffer; Str text; +char[32] textBuffer; void ready() { lockResolution(320, 180); @@ -12,12 +12,8 @@ void ready() { bool update(float dt) { prepareUi(); setUiFocus(0); - setUiStartPoint(Vec2()); - // Create the text field and print if enter is pressed. - // Text field combos: ctrl+backspace, ctrl+x - if (uiTextField(resolution, text, textBuffer)) { - println(text); - } + // Create the text field and print if enter is pressed. Combos: ctrl+backspace, ctrl+x + if (uiTextField(Rect(resolution), text, textBuffer)) println(text); return false; } diff --git a/examples/ui/handle.d b/examples/ui/handle.d index b426c3a..baeb16c 100644 --- a/examples/ui/handle.d +++ b/examples/ui/handle.d @@ -2,7 +2,7 @@ import parin; -auto handlePosition = Vec2(120, 60); +auto handleArea = Rect(40, 60, 60, 60); auto handleOptions = UiOptions(); void ready() { @@ -12,15 +12,13 @@ void ready() { bool update(float dt) { prepareUi(); setUiFocus(0); - setUiStartPoint(Vec2(8)); // Toggle the limit of the drag handle. - if (uiButton(Vec2(120, 24), "Limit: {}".format(handleOptions.dragLimit))) { - if (handleOptions.dragLimit) handleOptions.dragLimit = UiDragLimit.none; - else handleOptions.dragLimit = UiDragLimit.viewport; + if (uiButton(Rect(8, 8, 120, 25), handleOptions.dragLimit.toStr())) { + handleOptions.dragLimit = handleOptions.dragLimit ? UiDragLimit.none : UiDragLimit.viewport; } // Create the drag handle and print if it is dragged. - if (uiDragHandle(Vec2(60), handlePosition, handleOptions)) { - println(handlePosition); + if (uiDragHandle(handleArea, handleOptions)) { + println(handleArea.position); } return false; } diff --git a/examples/ui/hello.d b/examples/ui/hello.d index edc0d5e..26bbcd1 100644 --- a/examples/ui/hello.d +++ b/examples/ui/hello.d @@ -2,8 +2,6 @@ import parin; -auto buttonText = "Hello world!"; - void ready() { lockResolution(320, 180); } @@ -13,12 +11,8 @@ bool update(float dt) { prepareUi(); // Disable the UI focus for this frame. Focus is only needed for UIs that support keyboard controls. setUiFocus(0); - // Set the starting point for subsequent UI items. - setUiStartPoint(Vec2(8)); // Create a button and print if it is clicked. - if (uiButton(Vec2(80, 30), buttonText)) { - println(buttonText); - } + if (uiButton(Rect(8, 8, 100, 25), "Hello world!")) println("World: Hi!"); return false; } diff --git a/examples/ui/layout.d b/examples/ui/layout.d index c6a08a7..ec8695b 100644 --- a/examples/ui/layout.d +++ b/examples/ui/layout.d @@ -2,8 +2,10 @@ import parin; -auto textSize = Vec2(90, 24); -auto buttonSize = Vec2(20); +auto groupHeight = 20; +auto groupMargin = 2; +auto buttonWidth = 20; +auto textWidth = 90; void ready() { lockResolution(320, 180); @@ -12,15 +14,19 @@ void ready() { bool update(float dt) { prepareUi(); setUiFocus(0); - setUiStartPoint(Vec2(8)); - // Create a horizontal layout for arranging subsequent UI items. - useUiLayout(Layout.h); - uiText(textSize, "Cool Button", UiOptions(Alignment.left)); - if (uiButton(buttonSize, "")) println("Cool"); - // Create a new horizontal layout under the previous layout. - useUiLayout(Layout.h); - uiText(textSize, "Super Button", UiOptions(Alignment.left)); - if (uiButton(buttonSize, "")) println("Super"); + // Create an area for arranging UI items. + auto area = Rect(Vec2(8), resolution - Vec2(8)); + auto group = Rect(); + // Group 1. + group = area.subTop(groupHeight); + uiText(group.subLeft(textWidth), "Cool Button", UiOptions(Alignment.left)); + if (uiButton(group.subLeft(buttonWidth), "")) println("Cool"); + // Margin. + area.subTop(groupMargin); + // Group 2. + group = area.subTop(groupHeight); + uiText(group.subLeft(textWidth), "Super Button", UiOptions(Alignment.left)); + if (uiButton(group.subLeft(buttonWidth), "")) println("Super"); return false; } diff --git a/examples/ui/menu.d b/examples/ui/menu.d index 33f8484..1cd3f7a 100644 --- a/examples/ui/menu.d +++ b/examples/ui/menu.d @@ -2,8 +2,10 @@ import parin; -auto buttonSize = Vec2(70, 24); auto activeMenu = 0; +auto buttonWidth = 70; +auto buttonHeight = 25; +auto buttonMargin = 2; IStr[4] mainMenu = [ "Start", @@ -12,9 +14,8 @@ IStr[4] mainMenu = [ "Quit", ]; -IStr[3] continueMenu = [ +IStr[2] continueMenu = [ "Save 1", - "Save 2", "Back", ]; @@ -36,18 +37,20 @@ bool update(float dt) { if (activeMenu == 1) menu = continueMenu[]; else if (activeMenu == 2) menu = settingsMenu[]; // Draw the menu. - auto menuPoint = resolution * Vec2(0.5); - menuPoint.x -= buttonSize.x * 0.5; - menuPoint.y -= (buttonSize.y * menu.length + uiMargin * (menu.length - 1)) * 0.5; - setUiStartPoint(menuPoint); + auto area = Rect( + resolution * Vec2(0.5), + buttonWidth, + buttonHeight * menu.length + buttonMargin * (menu.length - 1), + ).area(Hook.center); foreach (item; menu) { - if (uiButton(buttonSize, item)) { + if (uiButton(area.subTop(buttonHeight), item)) { println(item); if (activeMenu == 0 && item == "Continue") activeMenu = 1; if (activeMenu == 0 && item == "Settings") activeMenu = 2; if (item == "Back") activeMenu = 0; if (item == "Quit") return true; } + area.subTop(buttonMargin); } return false; } diff --git a/examples/ui/playground.d b/examples/ui/playground.d deleted file mode 100644 index ec7f6a8..0000000 --- a/examples/ui/playground.d +++ /dev/null @@ -1,39 +0,0 @@ -/// This example shows almost every UI item of Parin. - -import parin; - -char[20] textFieldBuffer; -Str textFieldText; - -auto handleSize = Vec2(140, 7); -auto buttonSize = Vec2(60, 20); -auto textSize = Vec2(140, 12); -auto uiPoint = Vec2(); - -void ready() { - lockResolution(320, 180); -} - -bool update(float dt) { - prepareUi(); - setUiFocus(0); - if (Keyboard.f11.isPressed) toggleIsFullscreen(); - - useUiLayout(Layout.h); - uiDragHandle(handleSize, uiPoint); - - useUiLayout(Layout.h); - if (uiButton(buttonSize, "Button")) println("Button"); - - useUiLayout(Layout.h); - uiText(textSize, "Hello world!"); - - useUiLayout(Layout.h); - uiTextField(textSize, textFieldText, textFieldBuffer); - - return false; -} - -void finish() { } - -mixin runGame!(ready, update, finish); diff --git a/examples/ui/viewport.d b/examples/ui/viewport.d index 0498e78..d63eac9 100644 --- a/examples/ui/viewport.d +++ b/examples/ui/viewport.d @@ -17,9 +17,8 @@ bool update(float dt) { // Set the viewport state for subsequent UI items. setUiViewportState(viewportPosition, viewport.size, viewportScale); viewport.attach(); - setUiStartPoint(Vec2(8)); foreach (i; 0 .. 3) { - if (uiButton(Vec2(19), i.toStr())) println(i); + if (uiButton(Rect(8, 8 + i * 22, 20, 20), i.toStr())) println(i); } viewport.detach(); drawViewport(viewport, viewportPosition, DrawOptions(viewportScale)); diff --git a/source/parin/ui.d b/source/parin/ui.d index a3e9fdc..2691272 100644 --- a/source/parin/ui.d +++ b/source/parin/ui.d @@ -18,9 +18,7 @@ import parin.engine; UiState uiState; UiState uiPreviousState; -enum defaultUiAlpha = 220; -enum defaultUiMargin = 1; -enum defaultUiBorderThickness = 1; +enum defaultUiAlpha = 200; enum defaultUiDisabledColor = 0x202020.toRgb(); enum defaultUiIdleColor = 0x414141.toRgb(); enum defaultUiHotColor = 0x818181.toRgb(); @@ -39,8 +37,13 @@ enum UiDragLimit: ubyte { struct UiOptions { FontId font = FontId(); + Color disabledColor = defaultUiDisabledColor; + Color idleColor = defaultUiIdleColor; + Color hotColor = defaultUiHotColor; + Color activeColor = defaultUiActiveColor; + Alignment alignment = Alignment.center; - short alignmentOffset = defaultUiBorderThickness; + short alignmentOffset = 0; UiDragLimit dragLimit = UiDragLimit.viewport; Vec2 dragLimitX = Vec2(-100000.0f, 100000.0f); Vec2 dragLimitY = Vec2(-100000.0f, 100000.0f); @@ -52,7 +55,7 @@ struct UiOptions { this.isDisabled = isDisabled; } - this(Alignment alignment, short alignmentOffset = defaultUiBorderThickness) { + this(Alignment alignment, short alignmentOffset = 0) { this.alignment = alignment; this.alignmentOffset = alignmentOffset; } @@ -72,18 +75,8 @@ struct UiState { Vec2 viewportSize; Vec2 viewportScale = Vec2(1.0f); - Vec2 startPoint; - short margin = defaultUiMargin; - - Layout layout; - Vec2 layoutStartPoint; - Vec2 layoutStartPointOffest; - Vec2 layoutMaxItemSize; - Vec2 mousePressedPoint; Vec2 itemDragOffset; - Vec2 itemPoint; - Vec2 itemSize; short itemId; short hotItemId; short activeItemId; @@ -110,16 +103,6 @@ int findSpaceInTextField(IStr text) { void prepareUi() { setUiViewportState(Vec2(), resolution, Vec2(1.0f)); - uiState.startPoint = Vec2(); - uiState.margin = defaultUiMargin; - - uiState.layout = Layout.v; - uiState.layoutStartPoint = Vec2(); - uiState.layoutStartPointOffest = Vec2(); - uiState.layoutMaxItemSize = Vec2(); - - uiState.itemPoint = Vec2(); - uiState.itemSize = Vec2(); uiState.itemId = 0; uiState.hotItemId = 0; uiState.activeItemId = 0; @@ -165,75 +148,10 @@ void setUiViewportState(Vec2 point, Vec2 size, Vec2 scale) { } } -Vec2 uiStartPoint() { - return uiState.startPoint; -} - -void setUiStartPoint(Vec2 value) { - uiState.startPoint = value; - uiState.itemSize = Vec2(); - uiState.layoutStartPoint = value; - uiState.layoutStartPointOffest = Vec2(); - uiState.layoutMaxItemSize = Vec2(); -} - -short uiMargin() { - return uiState.margin; -} - -void setUiMargin(short value) { - uiState.margin = value; -} - -// TODO: THERE IS A WEIRD BUG WITH SPACING IF YOU DON"T PUT USE AT THE START OF EVERY GROUP. FIX IT. -// TODO: MAYBE ALSO MAKE THIS POOOOOOP MORE SIMPLE. -void useUiLayout(Layout value) { - if (uiState.layoutStartPointOffest) { - final switch (value) { - case Layout.v: - if (uiState.layoutStartPointOffest.x > uiState.layoutMaxItemSize.x) { - uiState.layoutStartPoint.x = uiState.layoutStartPoint.x + uiState.layoutStartPointOffest.x + uiState.margin; - } else { - uiState.layoutStartPoint.x += uiState.layoutMaxItemSize.x + uiState.margin; - } - uiState.layoutStartPointOffest = Vec2(); - uiState.layoutMaxItemSize.x = 0.0f; - break; - case Layout.h: - uiState.layoutStartPoint.x = uiState.startPoint.x; - if (uiState.layoutStartPointOffest.y > uiState.layoutMaxItemSize.y) { - uiState.layoutStartPoint.y = uiState.layoutStartPoint.y + uiState.layoutStartPointOffest.y + uiState.margin; - } else { - uiState.layoutStartPoint.y += uiState.layoutMaxItemSize.y + uiState.margin; - } - uiState.layoutStartPointOffest = Vec2(); - uiState.layoutMaxItemSize.y = 0.0f; - break; - } - } - uiState.layout = value; -} - -Vec2 uiLayoutStartPoint() { - return uiState.layoutStartPoint; -} - -Vec2 uiLayoutPoint() { - return uiState.layoutStartPoint + uiState.layoutStartPointOffest; -} - short uiItemId() { return uiState.itemId; } -Vec2 uiItemPoint() { - return uiState.itemPoint; -} - -Vec2 uiItemSize() { - return uiState.itemSize; -} - bool isUiItemHot() { return uiState.itemId == uiState.hotItemId; } @@ -326,17 +244,9 @@ void wrapUiFocus(short step, Sz length) { uiState.focusedItemId = wrap(cast(short) (uiState.focusedItemId + step), min, cast(short) (max + 1)); } -void updateUiState(Vec2 itemPoint, Vec2 itemSize, bool isHot, bool isActive, bool isClicked) { +void updateUiState(Rect area, bool isHot, bool isActive, bool isClicked) { uiPreviousState = uiState; - uiState.itemPoint = itemPoint; - uiState.itemSize = itemSize; uiState.itemId += 1; - if (itemSize.x > uiState.layoutMaxItemSize.x) uiState.layoutMaxItemSize.x = itemSize.x; - if (itemSize.y > uiState.layoutMaxItemSize.y) uiState.layoutMaxItemSize.y = itemSize.y; - final switch (uiState.layout) { - case Layout.v: uiState.layoutStartPointOffest.y += uiState.itemSize.y + uiState.margin; break; - case Layout.h: uiState.layoutStartPointOffest.x += uiState.itemSize.x + uiState.margin; break; - } if (isHot) { uiState.hotItemId = uiState.itemId; } @@ -347,7 +257,7 @@ void updateUiState(Vec2 itemPoint, Vec2 itemSize, bool isHot, bool isActive, boo if (isClicked) uiState.clickedItemId = uiState.itemId; if (uiState.mouseClickAction.isPressed && uiState.itemId == uiState.activeItemId) { auto m = uiMouse; - uiState.itemDragOffset = uiState.itemPoint - m; + uiState.itemDragOffset = area.position - m; uiState.draggedItemId = uiState.itemId; } if (uiState.draggedItemId) { @@ -355,13 +265,12 @@ void updateUiState(Vec2 itemPoint, Vec2 itemSize, bool isHot, bool isActive, boo } } -void updateUiText(Vec2 size, IStr text, UiOptions options = UiOptions()) { - updateUiState(uiLayoutPoint, size, false, false, false); +void updateUiText(Rect area, IStr text, UiOptions options = UiOptions()) { + updateUiState(area, false, false, false); } -void drawUiText(Vec2 size, IStr text, Vec2 point, UiOptions options = UiOptions()) { +void drawUiText(Rect area, IStr text, UiOptions options = UiOptions()) { auto font = options.font.isValid ? options.font.get() : engineFont; - auto area = Rect(point, size); auto textPoint = area.centerPoint; final switch (options.alignment) { case Alignment.left: textPoint.x += options.alignmentOffset; break; @@ -369,23 +278,21 @@ void drawUiText(Vec2 size, IStr text, Vec2 point, UiOptions options = UiOptions( case Alignment.right: textPoint.x -= options.alignmentOffset; break; } textPoint = textPoint.round(); - auto textOptions = DrawOptions(options.alignment, cast(int) size.x.round()); + auto textOptions = DrawOptions(options.alignment, cast(int) area.size.x.round()); textOptions.hook = Hook.center; if (options.isDisabled) textOptions.color.a = defaultUiAlpha; drawText(font, text, textPoint, textOptions); } -void uiText(Vec2 size, IStr text, UiOptions options = UiOptions()) { - updateUiText(size, text, options); - drawUiText(uiItemSize, text, uiItemPoint, options); +void uiText(Rect area, IStr text, UiOptions options = UiOptions()) { + updateUiText(area, text, options); + drawUiText(area, text, options); } -bool updateUiButton(Vec2 size, IStr text, UiOptions options = UiOptions()) { +bool updateUiButton(Rect area, IStr text, UiOptions options = UiOptions()) { auto font = options.font.isValid ? options.font.get() : engineFont; auto m = uiMouse; auto id = uiState.itemId + 1; - auto point = uiLayoutPoint; - auto area = Rect(point, size); auto isHot = area.hasPointInclusive(m); if (isHot) { uiState.previousMaxHotItemIdBuffer = cast(short) id; @@ -411,28 +318,26 @@ bool updateUiButton(Vec2 size, IStr text, UiOptions options = UiOptions()) { if (uiState.keyboardClickAction.isDown || uiState.gamepadClickAction.isDown) isActive = true; if (uiState.keyboardClickAction.isPressed || uiState.gamepadClickAction.isPressed) isClicked = true; } - updateUiState(area.position, area.size, isHot, isActive, isClicked); + updateUiState(area, isHot, isActive, isClicked); return isClicked; } -void drawUiButton(Vec2 size, IStr text, Vec2 point, bool isHot, bool isActive, UiOptions options = UiOptions()) { +void drawUiButton(Rect area, IStr text, bool isHot, bool isActive, UiOptions options = UiOptions()) { auto font = options.font.isValid ? options.font.get() : engineFont; - auto area = Rect(point, size); - if (options.isDisabled) drawRect(area, defaultUiDisabledColor); - else if (isActive) drawRect(area, defaultUiActiveColor); - else if (isHot) drawRect(area, defaultUiHotColor); - else drawRect(area, defaultUiIdleColor); - drawHollowRect(area, defaultUiBorderThickness, defaultUiDisabledColor.alpha(defaultUiAlpha)); - drawUiText(size, text, point, options); + if (options.isDisabled) drawRect(area, options.disabledColor); + else if (isActive) drawRect(area, options.activeColor); + else if (isHot) drawRect(area, options.hotColor); + else drawRect(area, options.idleColor); + drawUiText(area, text, options); } -bool uiButton(Vec2 size, IStr text, UiOptions options = UiOptions()) { - auto result = updateUiButton(size, text, options); - drawUiButton(uiItemSize, text, uiItemPoint, isUiItemHot, isUiItemActive, options); +bool uiButton(Rect area, IStr text, UiOptions options = UiOptions()) { + auto result = updateUiButton(area, text, options); + drawUiButton(area, text, isUiItemHot, isUiItemActive, options); return result; } -bool updateUiDragHandle(Vec2 size, ref Vec2 point, UiOptions options = UiOptions()) { +bool updateUiDragHandle(ref Rect area, UiOptions options = UiOptions()) { auto dragLimitX = Vec2(-100000.0f, 100000.0f); auto dragLimitY = Vec2(-100000.0f, 100000.0f); // NOTE: There is a potential bug here when size is bigger than the limit/viewport. I will ignore it for now. @@ -443,13 +348,13 @@ bool updateUiDragHandle(Vec2 size, ref Vec2 point, UiOptions options = UiOptions dragLimitY = Vec2(0.0f, uiState.viewportSize.y); break; case UiDragLimit.viewportAndX: - point.y = clamp(point.y, 0.0f, uiState.viewportSize.y - size.y); + area.position.y = clamp(area.position.y, 0.0f, uiState.viewportSize.y - area.size.y); dragLimitX = Vec2(0.0f, uiState.viewportSize.x); - dragLimitY = Vec2(point.y, point.y + size.y); + dragLimitY = Vec2(area.position.y, area.position.y + area.size.y); break; case UiDragLimit.viewportAndY: - point.x = clamp(point.x, 0.0f, uiState.viewportSize.x - size.x); - dragLimitX = Vec2(point.x, point.x + size.x); + area.position.x = clamp(area.position.x, 0.0f, uiState.viewportSize.x - area.size.x); + dragLimitX = Vec2(area.position.x, area.position.x + area.size.x); dragLimitY = Vec2(0.0f, uiState.viewportSize.y); break; case UiDragLimit.custom: @@ -457,51 +362,45 @@ bool updateUiDragHandle(Vec2 size, ref Vec2 point, UiOptions options = UiOptions dragLimitY = options.dragLimitY; break; case UiDragLimit.customAndX: - point.y = clamp(point.y, 0.0f, options.dragLimitY.y - size.y); + area.position.y = clamp(area.position.y, 0.0f, options.dragLimitY.y - area.size.y); dragLimitX = options.dragLimitX; - dragLimitY = Vec2(point.y, point.y + size.y); + dragLimitY = Vec2(area.position.y, area.position.y + area.size.y); break; case UiDragLimit.customAndY: - point.x = clamp(point.x, 0.0f, options.dragLimitX.y - size.x); - dragLimitX = Vec2(point.x, point.x + size.x); + area.position.x = clamp(area.position.x, 0.0f, options.dragLimitX.y - area.size.x); + dragLimitX = Vec2(area.position.x, area.position.x + area.size.x); dragLimitY = options.dragLimitY; break; } - size.x = clamp(size.x, 0.0f, dragLimitX.y - dragLimitX.x); - size.y = clamp(size.y, 0.0f, dragLimitY.y - dragLimitY.x); - point.x = clamp(point.x, dragLimitX.x, dragLimitX.y - size.x); - point.y = clamp(point.y, dragLimitY.x, dragLimitY.y - size.y); - setUiStartPoint(point); - updateUiButton(size, "", options); + area.position.x = clamp(area.position.x, dragLimitX.x, dragLimitX.y - area.size.x); + area.position.y = clamp(area.position.y, dragLimitY.x, dragLimitY.y - area.size.y); + updateUiButton(area, "", options); if (isUiItemDragged) { auto m = (mouse - uiState.viewportPoint) / uiState.viewportScale; // NOTE: Maybe this should be a function? - point.y = clamp(m.y + uiDragOffset.y, dragLimitY.x, dragLimitY.y - size.y); - point.x = clamp(m.x + uiDragOffset.x, dragLimitX.x, dragLimitX.y - size.x); + area.position.y = clamp(m.y + uiDragOffset.y, dragLimitY.x, dragLimitY.y - area.size.y); + area.position.x = clamp(m.x + uiDragOffset.x, dragLimitX.x, dragLimitX.y - area.size.x); uiState = uiPreviousState; - setUiStartPoint(point); - updateUiButton(size, "", options); + updateUiButton(area, "", options); return true; } else { return false; } } -void drawUiDragHandle(Vec2 size, Vec2 point, bool isHot, bool isActive, UiOptions options = UiOptions()) { - drawUiButton(size, "", point, isHot, isActive, options); - drawHollowRect(Rect(point, size), defaultUiBorderThickness, defaultUiDisabledColor.alpha(defaultUiAlpha)); +void drawUiDragHandle(Rect area, bool isHot, bool isActive, UiOptions options = UiOptions()) { + drawUiButton(area, "", isHot, isActive, options); } -bool uiDragHandle(Vec2 size, ref Vec2 point, UiOptions options = UiOptions()) { - auto result = updateUiDragHandle(size, point, options); - drawUiDragHandle(uiItemSize, uiItemPoint, isUiItemHot, isUiItemActive, options); +bool uiDragHandle(ref Rect area, UiOptions options = UiOptions()) { + auto result = updateUiDragHandle(area, options); + drawUiDragHandle(area, isUiItemHot, isUiItemActive, options); return result; } // TODO: Add support for right-to-left text. @trusted -bool updateUiTextField(Vec2 size, ref Str text, Str textBuffer, UiOptions options = UiOptions()) { - auto point = uiLayoutPoint; +bool updateUiTextField(Rect area, ref Str text, Str textBuffer, UiOptions options = UiOptions()) { if (options.isDisabled) { // Look, I am funny. } else if (Keyboard.x.isPressed && (Keyboard.ctrl.isDown || Keyboard.alt.isDown)) { @@ -575,22 +474,21 @@ bool updateUiTextField(Vec2 size, ref Str text, Str textBuffer, UiOptions option } } } - updateUiState(point, size, false, false, false); + updateUiState(area, false, false, false); return uiState.keyboardClickAction.isPressed; } // TODO: Add support for right-to-left text. -void drawUiTextField(Vec2 size, Str text, Vec2 point, UiOptions options = UiOptions()) { +void drawUiTextField(Rect area, Str text, UiOptions options = UiOptions()) { auto font = options.font.isValid ? options.font.get() : engineFont; - drawUiText(size, text, point, options); + drawUiText(area, text, options); // TODO: Make that text thing a function doood. - auto area = Rect(point, size); auto textPoint = area.centerPoint; auto textSize = measureTextSize(font, text); final switch (options.alignment) { - case Alignment.left: textPoint.x = point.x + options.alignmentOffset; break; + case Alignment.left: textPoint.x = area.position.x + options.alignmentOffset; break; case Alignment.center: textSize.x *= 0.5f; break; - case Alignment.right: textPoint.x = point.x + size.x - options.alignmentOffset; textSize.x = 0.0f; break; + case Alignment.right: textPoint.x = area.position.x + area.size.x - options.alignmentOffset; textSize.x = 0.0f; break; } if (!options.isDisabled) { auto rect = Rect( @@ -599,15 +497,15 @@ void drawUiTextField(Vec2 size, Str text, Vec2 point, UiOptions options = UiOpti font.size * 0.08f, font.size).area(Hook.center, ); if (rect.size.x <= 1.0f) rect.size.x = 1.0f; - drawRect(rect, defaultUiDisabledColor.alpha(defaultUiAlpha)); + drawRect(rect, options.disabledColor.alpha(defaultUiAlpha)); } } // Combos: // ctrl|alt + backsapce : Remove word. // ctrl|alt + x : Remove everything. -bool uiTextField(Vec2 size, ref Str text, Str textBuffer, UiOptions options = UiOptions()) { - auto result = updateUiTextField(size, text, textBuffer, options); - drawUiTextField(uiItemSize, text, uiItemPoint, options); +bool uiTextField(Rect area, ref Str text, Str textBuffer, UiOptions options = UiOptions()) { + auto result = updateUiTextField(area, text, textBuffer, options); + drawUiTextField(area, text, options); return result; }