diff --git a/examples/kanban_app.php b/examples/kanban_app.php index 82984a9..541503e 100644 --- a/examples/kanban_app.php +++ b/examples/kanban_app.php @@ -211,11 +211,7 @@ final class KanbanBoardView extends Container $this->saveBoards(); $this->renderBoards(); - $msg = sprintf( - '"%s" nach "%s" verschoben.', - $movedTask['title'], - $this->getBoardTitle($targetBoardId), - ); + $msg = sprintf('"%s" nach "%s" verschoben.', $movedTask['title'], $this->getBoardTitle($targetBoardId)); $this->statusLabel->setText($msg); if (defined('DEBUG_EVENTS') && DEBUG_EVENTS) { error_log('[Kanban] ' . $msg); @@ -330,7 +326,7 @@ if (empty($boards)) { ]; file_put_contents($storagePath, json_encode($boards, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), LOCK_EX); } -define('DEBUG_EVENTS', true); +define('DEBUG_EVENTS', false); $app = new Application(); $window = new Window('Kanban Beispiel', 1200, 800); @@ -362,17 +358,13 @@ if (function_exists('sdl_get_display_content_scale')) { $densityText .= ($densityText !== '' ? ' | ' : '') . sprintf('ContentScale: %.2f', $contentScale); } // Fallback: effektiven Scale aus WindowSize vs. WindowSizeInPixels berechnen -if ( - function_exists('sdl_get_window_size') && - function_exists('sdl_get_window_size_in_pixels') -) { +if (function_exists('sdl_get_window_size') && function_exists('sdl_get_window_size_in_pixels')) { $logical = sdl_get_window_size($window->getWindowResource()); $pixels = sdl_get_window_size_in_pixels($window->getWindowResource()); if (is_array($logical) && is_array($pixels) && $logical[0] > 0 && $logical[1] > 0) { $scaleX = $pixels[0] / $logical[0]; $scaleY = $pixels[1] / $logical[1]; - $densityText .= ($densityText !== '' ? ' | ' : '') . - sprintf('EffectiveScale: %.2f x %.2f', $scaleX, $scaleY); + $densityText .= ($densityText !== '' ? ' | ' : '') . sprintf('EffectiveScale: %.2f x %.2f', $scaleX, $scaleY); } } if (function_exists('sdl_get_current_video_driver')) { @@ -385,7 +377,10 @@ if ($densityText !== '') { $statusLabel->setText('Bereit. ' . $densityText); } -$scaleInput = new TextInput('Scale (z.B. 1.0 oder 2.0)', 'w-40 border border-gray-300 rounded px-3 py-2 bg-white text-black'); +$scaleInput = new TextInput( + 'Scale (z.B. 1.0 oder 2.0)', + 'w-40 border border-gray-300 rounded px-3 py-2 bg-white text-black', +); $scaleInput->setOnChange(function (string $value) use ($statusLabel): void { $value = trim($value); if ($value === '') { diff --git a/examples/kanban_data.json b/examples/kanban_data.json index e8857a9..5a3b90d 100644 --- a/examples/kanban_data.json +++ b/examples/kanban_data.json @@ -2,17 +2,23 @@ { "id": "board_691661d89de624.46726087", "title": "Backlog", - "tasks": [] - }, - { - "id": "board_691661d89de806.79123800", - "title": "In Arbeit", "tasks": [ { "id": "task_691661d89de735.41071535", "title": "Idee sammeln", "note": "" }, + { + "id": "task_691661d89de8e0.86926319", + "title": "UI Grundlayout", + "note": "" + } + ] + }, + { + "id": "board_691661d89de806.79123800", + "title": "In Arbeit", + "tasks": [ { "id": "task_691661d89de7a0.19655479", "title": "Mockups skizzieren", @@ -23,13 +29,7 @@ { "id": "board_691661d89de894.20053237", "title": "Erledigt", - "tasks": [ - { - "id": "task_691661d89de8e0.86926319", - "title": "UI Grundlayout", - "note": "" - } - ] + "tasks": [] }, { "id": "board_69170bcc2be8c6.34720864", diff --git a/src/Ui/Component.php b/src/Ui/Component.php index 5a2a87d..0a9e5b6 100644 --- a/src/Ui/Component.php +++ b/src/Ui/Component.php @@ -403,10 +403,10 @@ abstract class Component Profiler::start('render_cached'); // Render cached texture sdl_render_texture($renderer, $texture, [ - 'x' => $this->viewport->x, - 'y' => $this->viewport->y, - 'w' => $this->viewport->width, - 'h' => $this->viewport->height, + 'x' => $this->viewport->x * $this->viewport->uiScale, + 'y' => $this->viewport->y * $this->viewport->uiScale, + 'w' => $this->viewport->width * $this->viewport->uiScale, + 'h' => $this->viewport->height * $this->viewport->uiScale, ]); Profiler::end('render_cached'); Profiler::end('render'); @@ -445,13 +445,12 @@ abstract class Component // SDL3: sdl_rounded_box_ex uses (x1, y1, x2, y2) instead of (x, y, w, h) $x2 = $this->viewport->x + $this->viewport->width; $y2 = $this->viewport->y + $this->viewport->height; - sdl_rounded_box_ex( $renderer, - (int) $this->viewport->x, - (int) $this->viewport->y, - (int) $x2, - (int) $y2, + ((int) $this->viewport->x) * $this->viewport->uiScale, + ((int) $this->viewport->y) * $this->viewport->uiScale, + ((int) $x2) * $this->viewport->uiScale, + ((int) $y2) * $this->viewport->uiScale, $border->roundTopLeft ?? 0, $border->roundTopRight ?? 0, $border->roundBottomRight ?? 0, @@ -463,20 +462,20 @@ abstract class Component ); } else { sdl_render_fill_rect($renderer, [ - 'x' => $this->viewport->x, - 'y' => $this->viewport->y, - 'w' => $this->viewport->width, - 'h' => $this->viewport->height, + 'x' => $this->viewport->x * $this->viewport->uiScale, + 'y' => $this->viewport->y * $this->viewport->uiScale, + 'w' => $this->viewport->width * $this->viewport->uiScale, + 'h' => $this->viewport->height * $this->viewport->uiScale, ]); } } if (defined('DEBUG_RENDERING') && DEBUG_RENDERING) { sdl_set_render_draw_color($renderer, rand(0, 255), rand(0, 255), rand(0, 255), 10); sdl_render_rect($renderer, [ - 'x' => $this->viewport->x, - 'y' => $this->viewport->y, - 'w' => $this->viewport->width, - 'h' => $this->viewport->height, + 'x' => $this->viewport->x * $this->viewport->uiScale, + 'y' => $this->viewport->y * $this->viewport->uiScale, + 'w' => $this->viewport->width * $this->viewport->uiScale, + 'h' => $this->viewport->height * $this->viewport->uiScale, ]); } @@ -906,7 +905,7 @@ abstract class Component } } - $temp[$y * $width + $x] = $count > 0 ? (int) ($alphaSum / $count) : 0; + $temp[($y * $width) + $x] = $count > 0 ? ((int) ($alphaSum / $count)) : 0; } } @@ -916,8 +915,16 @@ abstract class Component /** * Create a blurred shadow texture */ - private function createShadowTexture(&$renderer, int $width, int $height, int $blurRadius, int $alpha, int $r = 0, int $g = 0, int $b = 0): mixed - { + private function createShadowTexture( + &$renderer, + int $width, + int $height, + int $blurRadius, + int $alpha, + int $r = 0, + int $g = 0, + int $b = 0, + ): mixed { if ($width <= 0 || $height <= 0) { return null; } @@ -928,9 +935,9 @@ abstract class Component // Fill only the inner rectangle with semi-transparent color // Leave a border for the blur to spread into $margin = $blurRadius + 2; - for ($y = $margin; $y < $height - $margin; $y++) { - for ($x = $margin; $x < $width - $margin; $x++) { - $alphaMap[$y * $width + $x] = $alpha; + for ($y = $margin; $y < ($height - $margin); $y++) { + for ($x = $margin; $x < ($width - $margin); $x++) { + $alphaMap[($y * $width) + $x] = $alpha; } } @@ -946,13 +953,7 @@ abstract class Component } // Create texture - $texture = sdl_create_texture( - $renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STATIC, - $width, - $height - ); + $texture = sdl_create_texture($renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, $width, $height); if (!$texture) { return null; @@ -993,7 +994,7 @@ abstract class Component $alpha = $shadowProps['alpha']; if ($shadow->opacity !== null) { // Convert percentage to 0-255 range and apply to base alpha - $alpha = (int)(($shadow->opacity / 100) * 255); + $alpha = (int) (($shadow->opacity / 100) * 255); } // Get shadow color (default to black if not specified) @@ -1008,13 +1009,13 @@ abstract class Component // Create shadow texture with blur $shadowTexture = $this->createShadowTexture( $renderer, - (int)$this->viewport->width, - (int)$this->viewport->height, + (int) $this->viewport->width, + (int) $this->viewport->height, $shadowProps['blur'], $alpha, $r, $g, - $b + $b, ); if (!$shadowTexture) { diff --git a/src/Ui/Viewport.php b/src/Ui/Viewport.php index 7da977d..17d6d6f 100644 --- a/src/Ui/Viewport.php +++ b/src/Ui/Viewport.php @@ -18,5 +18,6 @@ class Viewport public $addX = 0, public $addY = 0, public MediaQueryEnum $windowMediaQuery = MediaQueryEnum::normal, + public float $uiScale = 1, ) {} } diff --git a/src/Ui/Window.php b/src/Ui/Window.php index 625cba5..080110f 100644 --- a/src/Ui/Window.php +++ b/src/Ui/Window.php @@ -17,7 +17,7 @@ class Window private Viewport $viewport; private bool $shouldBeReLayouted = true; private float $pixelRatio = 1.0; - private float $uiScale = 1.0; + private float $uiScale = 2.0; private bool $shouldClose = false; private $onResize = null; private $onFpsChange = null; @@ -51,6 +51,7 @@ class Window $flags = SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_RESIZABLE; $this->window = sdl_create_window($title, $width, $height, $flags); + if (!$this->window) { throw new \Exception('Failed to create window: ' . sdl_get_error()); } @@ -58,6 +59,7 @@ class Window // Get window ID for event routing $this->windowId = sdl_get_window_id($this->window); + $this->uiScale = sdl_get_window_display_scale($this->window); // Enable text input for this window sdl_start_text_input($this->window); @@ -82,8 +84,8 @@ class Window windowHeight: $this->height, width: $this->width, height: $this->height, + uiScale: $this->uiScale, ); - $this->updatePixelRatio(); $this->lastFpsUpdate = microtime(true);