From b53b1cc30686c714621bd719f30587bcdc4a29a7 Mon Sep 17 00:00:00 2001 From: Mario Deluna <956212+mario-deluna@users.noreply.github.com> Date: Mon, 9 Sep 2024 23:40:57 +0200 Subject: [PATCH] Some work on GUI --- src/FlyUI/FUIButton.php | 48 ++++++++++++++++++++++++++-------- src/FlyUI/FUICard.php | 2 +- src/FlyUI/FUILayout.php | 9 +++++++ src/FlyUI/FUIRenderContext.php | 21 +++++++++++++-- src/FlyUI/FUIText.php | 33 ++++++++++++++++++++++- src/FlyUI/FUITheme.php | 14 ++++++++++ src/FlyUI/FlyUI.php | 6 ++--- src/Runtime/GameLoop.php | 15 ++++++++++- 8 files changed, 129 insertions(+), 19 deletions(-) diff --git a/src/FlyUI/FUIButton.php b/src/FlyUI/FUIButton.php index 5326494..b1d4ae7 100644 --- a/src/FlyUI/FUIButton.php +++ b/src/FlyUI/FUIButton.php @@ -21,6 +21,12 @@ class FUIButton extends FUIView public string $buttonId; + /** + * If set to true, the button will take the full width of the parent container + * instead of basing its size on the text width + */ + public bool $fullWidth = false; + /** * Constructs a new view */ @@ -30,7 +36,7 @@ public function __construct( ?string $buttonId = null ) { - parent::__construct(FlyUI::$instance->theme->buttonPadding); + parent::__construct(FlyUI::$instance->theme->buttonPadding->copy()); $this->backgroundColor = FlyUI::$instance->theme->buttonPrimaryBackgroundColor; $this->hoverBackgroundColor = FlyUI::$instance->theme->buttonPrimaryHoverBackgroundColor; @@ -52,6 +58,15 @@ public function setId(string $id) : self return $this; } + /** + * Sets the button to full width mode + */ + public function setFullWidth(bool $fullWidth = true) : self + { + $this->fullWidth = $fullWidth; + return $this; + } + /** * Returns the height of the current view and its children * This is used for layouting purposes @@ -68,11 +83,19 @@ public function getEstimatedHeight(FUIRenderContext $ctx) : float */ public function getEstimatedWidth(FUIRenderContext $ctx) : float { - $ctx->ensureFontFace('inter-semibold'); + if ($this->fullWidth) { + return $ctx->containerSize->x; + } + + $ctx->ensureSemiBoldFontFace(); $ctx->vg->fontSize($this->fontSize); return $ctx->vg->textBounds(0, 0, $this->text) + $this->padding->x * 2; } + private const BUTTON_PRESS_NONE = 0; + private const BUTTON_PRESS_STARTED = 1; + private const BUTTON_PRESS_ENDED = 2; + /** * Renders the current view using the provided context */ @@ -85,12 +108,12 @@ public function render(FUIRenderContext $ctx) : float $ctx->containerSize->y = $height; $ctx->containerSize->x = $width; - // Check if the mouse is inside the button + // check if the mouse is inside the button $isInside = $ctx->isHovered(); static $fuiButtonPressStates = []; if (!isset($fuiButtonPressStates[$this->buttonId])) { - $fuiButtonPressStates[$this->buttonId] = false; + $fuiButtonPressStates[$this->buttonId] = self::BUTTON_PRESS_NONE; } if ($isInside && $ctx->input->isMouseButtonPressed(MouseButton::LEFT)) { @@ -109,15 +132,16 @@ public function render(FUIRenderContext $ctx) : float ); $ctx->vg->stroke(); - - if (!$fuiButtonPressStates[$this->buttonId]) { - $fuiButtonPressStates[$this->buttonId] = true; - if ($this->onClick !== null) { - ($this->onClick)(); - } + if ($fuiButtonPressStates[$this->buttonId] === self::BUTTON_PRESS_NONE) { + $fuiButtonPressStates[$this->buttonId] = self::BUTTON_PRESS_STARTED; + } + } else if ($isInside && $fuiButtonPressStates[$this->buttonId] === self::BUTTON_PRESS_STARTED) { + $fuiButtonPressStates[$this->buttonId] = self::BUTTON_PRESS_ENDED; + if ($this->onClick) { + ($this->onClick)(); } } else { - $fuiButtonPressStates[$this->buttonId] = false; + $fuiButtonPressStates[$this->buttonId] = self::BUTTON_PRESS_NONE; } // render the button background @@ -146,6 +170,8 @@ public function render(FUIRenderContext $ctx) : float // wile ignoring letters like 'g' or 'y' that go below the baseline $ctx->origin->y = floor($ctx->origin->y + $this->fontSize * 0.15); + $ctx->ensureSemiBoldFontFace(); + $ctx->vg->fontSize($this->fontSize); $ctx->vg->textAlign(VGAlign::CENTER | VGAlign::MIDDLE); $ctx->vg->fillColor($this->textColor); $ctx->vg->text($ctx->origin->x, $ctx->origin->y, $this->text); diff --git a/src/FlyUI/FUICard.php b/src/FlyUI/FUICard.php index 88e617b..9671235 100644 --- a/src/FlyUI/FUICard.php +++ b/src/FlyUI/FUICard.php @@ -19,7 +19,7 @@ class FUICard extends FUILayout */ public function __construct() { - parent::__construct(FlyUI::$instance->theme->cardPadding); + parent::__construct(FlyUI::$instance->theme->cardPadding->copy()); $this->backgroundColor = FlyUI::$instance->theme->cardBackgroundColor; $this->borderRadius = FlyUI::$instance->theme->cardBorderRadius; diff --git a/src/FlyUI/FUILayout.php b/src/FlyUI/FUILayout.php index 2794866..0e8449f 100644 --- a/src/FlyUI/FUILayout.php +++ b/src/FlyUI/FUILayout.php @@ -229,6 +229,15 @@ public function verticalFit() : self return $this; } + /** + * Sets the vertical spacing between the children + */ + public function spacingY(float $spacing) : self + { + $this->spacingY = $spacing; + return $this; + } + /** * Returns the height of the content aka the sum of all children */ diff --git a/src/FlyUI/FUIRenderContext.php b/src/FlyUI/FUIRenderContext.php index 2b94695..a61b6c3 100644 --- a/src/FlyUI/FUIRenderContext.php +++ b/src/FlyUI/FUIRenderContext.php @@ -26,7 +26,7 @@ class FUIRenderContext /** * Current font face */ - public string $fontFace = ''; + private string $fontFace = ''; /** * Returns true if the mouse is currently hovering over the current bounds @@ -71,6 +71,22 @@ public function ensureFontFace(string $fontFace) : void $this->fontFace = $fontFace; } } + + /** + * Ensures the default "regular" font face is set + */ + public function ensureRegularFontFace() : void + { + $this->ensureFontFace($this->theme->regularFont); + } + + /** + * Ensures the default "semi bold" font face is set + */ + public function ensureSemiBoldFontFace() : void + { + $this->ensureFontFace($this->theme->semiBoldFont); + } /** * Sets a static value (persistant data, over multiple frames) @@ -95,7 +111,8 @@ public function getStaticValue(string $key, mixed $default = null) : mixed */ public function __construct( public VGContext $vg, - public Input $input + public Input $input, + public FUITheme $theme ) { $this->origin = new Vec2(0, 0); diff --git a/src/FlyUI/FUIText.php b/src/FlyUI/FUIText.php index 916fb1c..bf9013e 100644 --- a/src/FlyUI/FUIText.php +++ b/src/FlyUI/FUIText.php @@ -8,8 +8,16 @@ class FUIText extends FUIView { + /** + * The font size of the text + */ public float $fontSize; + /** + * Should the text be bold + */ + public bool $isBold = false; + /** * Constructs a new view */ @@ -23,6 +31,24 @@ public function __construct( $this->fontSize = FlyUI::$instance->theme->fontSize; } + /** + * Sets the font size of the text + */ + public function fontSize(float $size) : self + { + $this->fontSize = $size; + return $this; + } + + /** + * Sets the text to be bold + */ + public function bold() : self + { + $this->isBold = true; + return $this; + } + /** * Returns the height of the current view and its children * This is used for layouting purposes @@ -51,7 +77,12 @@ public function render(FUIRenderContext $ctx) : float // $ctx->vg->rect($ctx->origin->x, $ctx->origin->y, $ctx->containerSize->x, $height - 1); // $ctx->vg->fill(); - $ctx->ensureFontFace('inter-regular'); + if ($this->isBold) { + $ctx->ensureSemiBoldFontFace(); + } else { + $ctx->ensureRegularFontFace(); + } + $ctx->vg->textAlign(VGAlign::LEFT | VGAlign::TOP); $ctx->vg->fontSize($this->fontSize); $ctx->vg->fillColor(VGColor::black()); diff --git a/src/FlyUI/FUITheme.php b/src/FlyUI/FUITheme.php index 4977b66..0b8ecad 100644 --- a/src/FlyUI/FUITheme.php +++ b/src/FlyUI/FUITheme.php @@ -11,6 +11,20 @@ class FUITheme * ------------------------------ General --------------------------------- */ + /** + * Default font used for text, buttons, etc. + * FlyUI loads the `inter` font automatically, if you want to use a different font you + * are responsible for loading it yourself. + */ + public string $regularFont = 'inter-regular'; + + /** + * Default "semi bold" font. + * FlyUI loads the `inter` font automatically, if you want to use a different font you + * are responsible for loading it yourself. + */ + public string $semiBoldFont = 'inter-semibold'; + /** * The general padding used to space elements */ diff --git a/src/FlyUI/FlyUI.php b/src/FlyUI/FlyUI.php index 7a7cfc1..5398d3e 100644 --- a/src/FlyUI/FlyUI.php +++ b/src/FlyUI/FlyUI.php @@ -242,13 +242,13 @@ private function internalBeginFrame(Vec2 $resolution, float $contentScale = 1.0) */ private function internalEndFrame() : void { - $ctx = new FUIRenderContext($this->vgContext, $this->input); + $ctx = new FUIRenderContext($this->vgContext, $this->input, $this->theme); $ctx->containerSize = $this->currentResolution; $this->vgContext->reset(); - // set the inter font - $this->vgContext->fontFace('inter-regular'); + // set the default font face + $ctx->ensureRegularFontFace(); // let all views render itself $this->viewTree[0]->render($ctx); diff --git a/src/Runtime/GameLoop.php b/src/Runtime/GameLoop.php index b096a3f..eee1884 100644 --- a/src/Runtime/GameLoop.php +++ b/src/Runtime/GameLoop.php @@ -72,6 +72,11 @@ class GameLoop */ public int $tickTimeSampleCount = 60; + /** + * If set to true, the game loop will force stop, even if the delegate doesn't want to. + */ + private bool $forceStop = false; + /** * Constructor * @@ -208,6 +213,14 @@ public function getAverageFrameTimeFormatted() : string return $this->formatNStoHuman((int) $this->getAverageFrameTime()); } + /** + * Force stops the game loop. + */ + public function forceStop() : void + { + $this->forceStop = true; + } + /** * Starts and runs the game loop * @@ -225,7 +238,7 @@ public function start() : void $frameTickCount = 0; // loop forever until the delegate tells us to stop - while (!$this->delegate->shouldStop()) + while (!$this->delegate->shouldStop() && !$this->forceStop) { // determine delta time since last frame $deltaTime = Clock::now64() - $lastFrameStart;