Fixes
This commit is contained in:
parent
6e1b7c2b1b
commit
a1fabd3623
@ -1,75 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Check PHP version
|
|
||||||
if (PHP_VERSION_ID < 80100) {
|
|
||||||
die("This demo requires PHP 8.1+ for Fiber support.\nYour version: " . PHP_VERSION . "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$app = new Application('Button Example', 800, 600);
|
|
||||||
|
|
||||||
// Main container
|
|
||||||
$mainContainer = new Container(style: 'p-10 bg-gray-100');
|
|
||||||
|
|
||||||
// Title
|
|
||||||
$title = new Label(
|
|
||||||
text: 'Button Sizing Example',
|
|
||||||
style: 'text-xl text-black',
|
|
||||||
);
|
|
||||||
$mainContainer->addComponent($title);
|
|
||||||
|
|
||||||
// Button with m-10 p-10, should be: 12 (text) + 10 (padding-top) + 10 (padding-bottom) = 32px height
|
|
||||||
$button1 = new Button(
|
|
||||||
text: 'Click Me',
|
|
||||||
style: 'm-10 p-10 bg-blue-500 rounded-lg',
|
|
||||||
);
|
|
||||||
$mainContainer->addComponent($button1);
|
|
||||||
|
|
||||||
// Button with different padding
|
|
||||||
$button2 = new Button(
|
|
||||||
text: 'Another Button',
|
|
||||||
style: 'm-5 p-15 bg-green-500 hover:bg-green-200 rounded-lg',
|
|
||||||
onClick: function () {
|
|
||||||
echo 'test2';
|
|
||||||
},
|
|
||||||
);
|
|
||||||
$mainContainer->addComponent($button2);
|
|
||||||
|
|
||||||
// Button with no padding
|
|
||||||
$button3 = new Button(
|
|
||||||
text: 'No Padding',
|
|
||||||
style: 'm-10 bg-red-500 rounded-lg',
|
|
||||||
);
|
|
||||||
$mainContainer->addComponent($button3);
|
|
||||||
|
|
||||||
// Container with multiple labels (should stack)
|
|
||||||
$labelContainer = new Container(style: 'm-10 p-10 bg-white rounded-lg');
|
|
||||||
$labelContainer->addComponent(new Label(
|
|
||||||
text: 'Label 1',
|
|
||||||
style: 'text-black',
|
|
||||||
));
|
|
||||||
$labelContainer->addComponent(new Label(
|
|
||||||
text: 'Label 2',
|
|
||||||
style: 'text-black',
|
|
||||||
));
|
|
||||||
$labelContainer->addComponent(new Label(
|
|
||||||
text: 'Label 3',
|
|
||||||
style: 'text-black',
|
|
||||||
));
|
|
||||||
$mainContainer->addComponent($labelContainer);
|
|
||||||
|
|
||||||
// Info text
|
|
||||||
$info = new Label(
|
|
||||||
text: 'Containers should auto-size to their content',
|
|
||||||
style: 'text-black m-10',
|
|
||||||
);
|
|
||||||
$mainContainer->addComponent($info);
|
|
||||||
|
|
||||||
$app->setRoot($mainContainer);
|
|
||||||
$app->run();
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Check PHP version
|
|
||||||
if (PHP_VERSION_ID < 80100) {
|
|
||||||
die("This demo requires PHP 8.1+ for Fiber support.\nYour version: " . PHP_VERSION . "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$app = new Application('Flexbox Layout Demo', 800, 600);
|
|
||||||
|
|
||||||
// Main container with padding
|
|
||||||
$mainContainer = new Container(style: 'p-4 bg-gray-100');
|
|
||||||
|
|
||||||
// Example 1: Flex Row with basis
|
|
||||||
$row1 = new Container(style: 'flex flex-row bg-white m-2 p-2');
|
|
||||||
|
|
||||||
$box1 = new Container(style: 'basis-1/3 bg-blue-500 p-4');
|
|
||||||
$label1 = new Label(text: '33% Basis', style: 'text-white');
|
|
||||||
$box1->addComponent($label1);
|
|
||||||
|
|
||||||
$box2 = new Container(style: 'basis-1/3 bg-green-500 p-4');
|
|
||||||
$label2 = new Label(text: '33% Basis', style: 'text-white');
|
|
||||||
$box2->addComponent($label2);
|
|
||||||
|
|
||||||
$box3 = new Container(style: 'basis-1/3 bg-red-500 p-4');
|
|
||||||
$label3 = new Label(text: '33% Basis', style: 'text-white');
|
|
||||||
$box3->addComponent($label3);
|
|
||||||
|
|
||||||
$row1->addComponent($box1);
|
|
||||||
$row1->addComponent($box2);
|
|
||||||
$row1->addComponent($box3);
|
|
||||||
|
|
||||||
// Example 2: Flex Row with flex-grow
|
|
||||||
$row2 = new Container(style: 'flex flex-row bg-white m-2 p-2');
|
|
||||||
|
|
||||||
$fixedBox = new Container(style: 'w-200 bg-purple-500 p-4');
|
|
||||||
$fixedLabel = new Label(text: 'Fixed 200px', style: 'text-white');
|
|
||||||
$fixedBox->addComponent($fixedLabel);
|
|
||||||
|
|
||||||
$growBox = new Container(style: 'flex-1 bg-yellow-500 p-4');
|
|
||||||
$growLabel = new Label(text: 'Flex Grow (rest)', style: 'text-black');
|
|
||||||
$growBox->addComponent($growLabel);
|
|
||||||
|
|
||||||
$row2->addComponent($fixedBox);
|
|
||||||
$row2->addComponent($growBox);
|
|
||||||
|
|
||||||
// Example 3: Flex Column
|
|
||||||
$col1 = new Container(style: 'flex flex-col bg-white m-2 p-2 h-200');
|
|
||||||
|
|
||||||
$colBox1 = new Container(style: 'basis-1/2 bg-cyan-500 p-4');
|
|
||||||
$colLabel1 = new Label(text: '50% Height', style: 'text-white');
|
|
||||||
$colBox1->addComponent($colLabel1);
|
|
||||||
|
|
||||||
$colBox2 = new Container(style: 'basis-1/2 bg-orange-500 p-4');
|
|
||||||
$colLabel2 = new Label(text: '50% Height', style: 'text-white');
|
|
||||||
$colBox2->addComponent($colLabel2);
|
|
||||||
|
|
||||||
$col1->addComponent($colBox1);
|
|
||||||
$col1->addComponent($colBox2);
|
|
||||||
|
|
||||||
// Add all examples to main container
|
|
||||||
$mainContainer->addComponent($row1);
|
|
||||||
$mainContainer->addComponent($row2);
|
|
||||||
$mainContainer->addComponent($col1);
|
|
||||||
|
|
||||||
$app->setRoot($mainContainer);
|
|
||||||
$app->run();
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Check PHP version
|
|
||||||
if (PHP_VERSION_ID < 80100) {
|
|
||||||
die("This demo requires PHP 8.1+ for Fiber support.\nYour version: " . PHP_VERSION . "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$app = new Application('Overflow Scroll Demo', 800, 600);
|
|
||||||
|
|
||||||
// Main container
|
|
||||||
$mainContainer = new Container(style: 'p-4 bg-gray-100');
|
|
||||||
|
|
||||||
// Title
|
|
||||||
$title = new Label(text: 'Overflow Scroll Demo', style: 'text-xl text-black p-2');
|
|
||||||
$mainContainer->addComponent($title);
|
|
||||||
|
|
||||||
// Example 1: Vertical scroll with overflow-y-auto
|
|
||||||
$scrollContainer = new Container(style: 'overflow-y-auto bg-white m-4 p-4 h-200');
|
|
||||||
|
|
||||||
// Add many items to trigger overflow
|
|
||||||
for ($i = 1; $i <= 20; $i++) {
|
|
||||||
$item = new Container(style: 'bg-blue-500 m-2 p-3 rounded-lg');
|
|
||||||
$label = new Label(
|
|
||||||
text: "Item {$i} - Scroll vertically with mouse wheel or drag the scrollbar",
|
|
||||||
style: 'text-white'
|
|
||||||
);
|
|
||||||
$item->addComponent($label);
|
|
||||||
$scrollContainer->addComponent($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
$mainContainer->addComponent($scrollContainer);
|
|
||||||
|
|
||||||
// Example 2: Horizontal scroll with overflow-x-auto
|
|
||||||
$label2 = new Label(text: 'Horizontal Scroll:', style: 'text-black p-2');
|
|
||||||
$mainContainer->addComponent($label2);
|
|
||||||
|
|
||||||
$horizontalScroll = new Container(style: 'flex flex-row overflow-x-auto bg-white m-4 p-4 h-100');
|
|
||||||
|
|
||||||
for ($i = 1; $i <= 10; $i++) {
|
|
||||||
$box = new Container(style: 'w-150 bg-green-500 m-2 p-3 rounded-lg');
|
|
||||||
$boxLabel = new Label(text: "Box {$i}", style: 'text-white');
|
|
||||||
$box->addComponent($boxLabel);
|
|
||||||
$horizontalScroll->addComponent($box);
|
|
||||||
}
|
|
||||||
|
|
||||||
$mainContainer->addComponent($horizontalScroll);
|
|
||||||
|
|
||||||
// Instructions
|
|
||||||
$instructions = new Container(style: 'bg-yellow-200 p-4 m-4 rounded-lg');
|
|
||||||
$instructionText = new Label(
|
|
||||||
text: 'Use mouse wheel to scroll. Click and drag scrollbars.',
|
|
||||||
style: 'text-black'
|
|
||||||
);
|
|
||||||
$instructions->addComponent($instructionText);
|
|
||||||
$mainContainer->addComponent($instructions);
|
|
||||||
|
|
||||||
$app->setRoot($mainContainer);
|
|
||||||
$app->run();
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Check PHP version
|
|
||||||
if (PHP_VERSION_ID < 80100) {
|
|
||||||
die("This demo requires PHP 8.1+ for Fiber support.\nYour version: " . PHP_VERSION . "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$app = new Application('Button Example', 800, 600);
|
|
||||||
|
|
||||||
$container = new Container('p-4');
|
|
||||||
// Button with different padding
|
|
||||||
$button2 = new Button(
|
|
||||||
text: 'Another Button',
|
|
||||||
style: 'm-5 p-15 bg-lime-500 hover:bg-green-200',
|
|
||||||
);
|
|
||||||
|
|
||||||
$button2->setOnClickAsync(
|
|
||||||
onClickAsync: function () {
|
|
||||||
// Fetch data from API (example: JSON placeholder)
|
|
||||||
$url = 'https://jsonplaceholder.typicode.com/todos/1';
|
|
||||||
|
|
||||||
$context = stream_context_create([
|
|
||||||
'http' => [
|
|
||||||
'timeout' => 10,
|
|
||||||
'method' => 'GET',
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response = file_get_contents($url, false, $context);
|
|
||||||
|
|
||||||
if ($response === false) {
|
|
||||||
throw new \Exception('Failed to fetch data');
|
|
||||||
}
|
|
||||||
|
|
||||||
return json_decode($response, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
onComplete: function ($data) use ($container) {
|
|
||||||
$statusLabel = new Label(
|
|
||||||
text: 'Klicken Sie den Button, um Daten zu laden...',
|
|
||||||
style: 'text-base text-gray-700',
|
|
||||||
);
|
|
||||||
|
|
||||||
$resultLabel = new Label(
|
|
||||||
text: '',
|
|
||||||
style: 'text-sm text-blue-600',
|
|
||||||
);
|
|
||||||
|
|
||||||
$statusLabel->setText('✓ Daten erfolgreich geladen!');
|
|
||||||
|
|
||||||
$formatted = 'ID: ' . ($data['id'] ?? 'N/A') . "\n";
|
|
||||||
$formatted .= 'Titel: ' . ($data['title'] ?? 'N/A') . "\n";
|
|
||||||
$formatted .= 'Erledigt: ' . (($data['completed'] ?? false) ? 'Ja' : 'Nein');
|
|
||||||
|
|
||||||
$resultLabel->setText($formatted);
|
|
||||||
$container->addComponent($statusLabel);
|
|
||||||
$container->addComponent($resultLabel);
|
|
||||||
},
|
|
||||||
|
|
||||||
onError: function ($error) {},
|
|
||||||
);
|
|
||||||
$container->addComponent($button2);
|
|
||||||
$app->setRoot($container);
|
|
||||||
$app->run();
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
// Check PHP version
|
|
||||||
if (PHP_VERSION_ID < 80100) {
|
|
||||||
die("This demo requires PHP 8.1+ for Fiber support.\nYour version: " . PHP_VERSION . "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$app = new \PHPNative\Framework\Application('ToDo Demo', 700, 500);
|
|
||||||
$container = new Container('m-10 p-10 bg-lime-500');
|
|
||||||
$scrollContainer = new Container(style: 'overflow-y-auto bg-red m-4 p-4');
|
|
||||||
|
|
||||||
// Add many items to trigger overflow
|
|
||||||
for ($i = 1; $i <= 200; $i++) {
|
|
||||||
$item = new Container(style: 'bg-blue-500 m-2 p-3');
|
|
||||||
$label = new Label(
|
|
||||||
text: "Item {$i}",
|
|
||||||
style: 'text-green-500',
|
|
||||||
);
|
|
||||||
$item->addComponent($label);
|
|
||||||
$scrollContainer->addComponent($item);
|
|
||||||
}
|
|
||||||
$container->addComponent($scrollContainer);
|
|
||||||
$app->setRoot($container);
|
|
||||||
$app->run();
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
// Check PHP version
|
|
||||||
if (PHP_VERSION_ID < 80100) {
|
|
||||||
die("This demo requires PHP 8.1+ for Fiber support.\nYour version: " . PHP_VERSION . "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$app = new \PHPNative\Framework\Application('ToDo Demo', 700, 500);
|
|
||||||
$container = new \PHPNative\Ui\Widget\Container(style: 'm-10 p-10 flex-row rounded-xl bg-lime-200');
|
|
||||||
$containerContent = new \PHPNative\Ui\Widget\Container(style: 'flex-1 bg-lime-700');
|
|
||||||
$labelContent = new Label(
|
|
||||||
text: 'Todo App',
|
|
||||||
style: 'text-xl2 text-red-500',
|
|
||||||
);
|
|
||||||
$containerContent->addComponent($labelContent);
|
|
||||||
$container->addComponent($containerContent);
|
|
||||||
$containerMenu = new \PHPNative\Ui\Widget\Container(style: 'w-200 bg-lime-200');
|
|
||||||
$label = new Label(
|
|
||||||
text: 'Menu App',
|
|
||||||
style: 'text-red-500',
|
|
||||||
);
|
|
||||||
$containerMenu->addComponent($label);
|
|
||||||
$scrollContainer = new Container(style: 'overflow-y-auto bg-red m-4 p-4');
|
|
||||||
|
|
||||||
// Add many items to trigger overflow
|
|
||||||
for ($i = 1; $i <= 100; $i++) {
|
|
||||||
$item = new Container(style: 'bg-blue-500 m-2 p-3');
|
|
||||||
$label = new Label(
|
|
||||||
text: "Item {$i}",
|
|
||||||
style: 'text-green-500',
|
|
||||||
);
|
|
||||||
$item->addComponent($label);
|
|
||||||
$scrollContainer->addComponent($item);
|
|
||||||
}
|
|
||||||
$containerMenu->addComponent($scrollContainer);
|
|
||||||
$container->addComponent($containerMenu);
|
|
||||||
$app->setRoot($container);
|
|
||||||
$app->run();
|
|
||||||
@ -1,185 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
define('DEBUG_EVENTS', false);
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Create application
|
|
||||||
$app = new Application();
|
|
||||||
|
|
||||||
// Create main window
|
|
||||||
$mainWindow = $app->createWindow('Advanced Multi-Window Demo', 700, 500, 100, 100);
|
|
||||||
|
|
||||||
$windowCounter = 1;
|
|
||||||
|
|
||||||
// Main UI
|
|
||||||
$mainContainer = new Container('flex flex-col p-6 gap-4 bg-gray-50');
|
|
||||||
|
|
||||||
$title = new Label(
|
|
||||||
text: 'Advanced Multi-Window Demo',
|
|
||||||
style: 'text-2xl text-gray-900',
|
|
||||||
);
|
|
||||||
|
|
||||||
$subtitle = new Label(
|
|
||||||
text: 'Windows mit asynchronen Operationen',
|
|
||||||
style: 'text-base text-gray-600',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Button to create window with async data loading
|
|
||||||
$createAsyncWindowButton = new Button(
|
|
||||||
text: 'Window mit Async-Datenladung',
|
|
||||||
style: 'bg-purple-500 hover:bg-purple-700 text-white p-4 rounded-lg',
|
|
||||||
);
|
|
||||||
|
|
||||||
$createAsyncWindowButton->setOnClickAsync(
|
|
||||||
onClickAsync: function () use (&$windowCounter) {
|
|
||||||
// Simulate loading data in background
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
return [
|
|
||||||
'windowId' => $windowCounter++,
|
|
||||||
'data' => 'Daten erfolgreich geladen!',
|
|
||||||
'timestamp' => date('H:i:s'),
|
|
||||||
'items' => ['Item 1', 'Item 2', 'Item 3'],
|
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
onComplete: function ($result) use ($app) {
|
|
||||||
// Create window with loaded data
|
|
||||||
$windowId = $result['windowId'];
|
|
||||||
$newWindow = $app->createWindow(
|
|
||||||
"Data Window #{$windowId}",
|
|
||||||
500,
|
|
||||||
350,
|
|
||||||
150 + ($windowId * 30),
|
|
||||||
150 + ($windowId * 30),
|
|
||||||
);
|
|
||||||
|
|
||||||
$container = new Container('flex flex-col p-6 gap-3 bg-green-50');
|
|
||||||
|
|
||||||
$titleLabel = new Label(
|
|
||||||
text: "Data Window #{$windowId}",
|
|
||||||
style: 'text-xl text-gray-900',
|
|
||||||
);
|
|
||||||
|
|
||||||
$dataLabel = new Label(
|
|
||||||
text: $result['data'],
|
|
||||||
style: 'text-base text-green-700 p-2 bg-white rounded',
|
|
||||||
);
|
|
||||||
|
|
||||||
$timeLabel = new Label(
|
|
||||||
text: 'Geladen um: ' . $result['timestamp'],
|
|
||||||
style: 'text-sm text-gray-600',
|
|
||||||
);
|
|
||||||
|
|
||||||
$itemsLabel = new Label(
|
|
||||||
text: "Items:\n" . implode("\n", $result['items']),
|
|
||||||
style: 'text-sm text-gray-700 p-2 bg-white rounded',
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton = new Button(
|
|
||||||
text: 'Schließen',
|
|
||||||
style: 'bg-red-500 hover:bg-red-700 text-white p-3 rounded',
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton->setOnClick(function () use ($newWindow) {
|
|
||||||
$newWindow->close();
|
|
||||||
});
|
|
||||||
|
|
||||||
$container->addComponent($titleLabel);
|
|
||||||
$container->addComponent($dataLabel);
|
|
||||||
$container->addComponent($timeLabel);
|
|
||||||
$container->addComponent($itemsLabel);
|
|
||||||
$container->addComponent($closeButton);
|
|
||||||
|
|
||||||
$newWindow->setRoot($container);
|
|
||||||
},
|
|
||||||
|
|
||||||
onError: function ($error) {
|
|
||||||
error_log('Error creating window: ' . $error->getMessage());
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Button to create multiple windows at once
|
|
||||||
$createMultipleButton = new Button(
|
|
||||||
text: '3 Windows auf einmal erstellen',
|
|
||||||
style: 'bg-orange-500 hover:bg-orange-700 text-white p-4 rounded-lg',
|
|
||||||
);
|
|
||||||
|
|
||||||
$createMultipleButton->setOnClick(function () use ($app, &$windowCounter) {
|
|
||||||
for ($i = 0; $i < 3; $i++) {
|
|
||||||
$currentId = $windowCounter++;
|
|
||||||
$offset = $currentId * 40;
|
|
||||||
|
|
||||||
$newWindow = $app->createWindow("Batch Window #{$currentId}", 400, 250, 200 + $offset, 200 + ($i * 50));
|
|
||||||
|
|
||||||
$container = new Container('flex flex-col p-4 gap-2 bg-yellow-50');
|
|
||||||
|
|
||||||
$label = new Label(
|
|
||||||
text: "Batch Window #{$currentId}",
|
|
||||||
style: 'text-lg text-gray-900',
|
|
||||||
);
|
|
||||||
|
|
||||||
$info = new Label(
|
|
||||||
text: "Teil einer Batch-Erstellung ({$i}/3)",
|
|
||||||
style: 'text-sm text-gray-600',
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton = new Button(
|
|
||||||
text: 'X',
|
|
||||||
style: 'bg-red-500 hover:bg-red-700 text-white p-2 rounded',
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton->setOnClick(function () use ($newWindow) {
|
|
||||||
$newWindow->close();
|
|
||||||
});
|
|
||||||
|
|
||||||
$container->addComponent($label);
|
|
||||||
$container->addComponent($info);
|
|
||||||
$container->addComponent($closeButton);
|
|
||||||
|
|
||||||
$newWindow->setRoot($container);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Window count label
|
|
||||||
$windowCountLabel = new Label(
|
|
||||||
text: 'Offene Windows: 1',
|
|
||||||
style: 'text-sm text-blue-600 p-2 bg-white rounded',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update window count periodically
|
|
||||||
$mainContainer->addComponent($title);
|
|
||||||
$mainContainer->addComponent($subtitle);
|
|
||||||
$mainContainer->addComponent($windowCountLabel);
|
|
||||||
$mainContainer->addComponent($createAsyncWindowButton);
|
|
||||||
$mainContainer->addComponent($createMultipleButton);
|
|
||||||
|
|
||||||
// Info
|
|
||||||
$info = new Label(
|
|
||||||
text: 'Die UI bleibt responsive während des Ladens!',
|
|
||||||
style: 'text-xs text-gray-500 italic mt-4',
|
|
||||||
);
|
|
||||||
$mainContainer->addComponent($info);
|
|
||||||
|
|
||||||
// Quit button
|
|
||||||
$quitButton = new Button(
|
|
||||||
text: 'Beenden',
|
|
||||||
style: 'bg-red-600 hover:bg-red-800 text-white p-4 rounded-lg',
|
|
||||||
);
|
|
||||||
|
|
||||||
$quitButton->setOnClick(function () use ($app) {
|
|
||||||
$app->quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
$mainContainer->addComponent($quitButton);
|
|
||||||
|
|
||||||
$mainWindow->setRoot($mainContainer);
|
|
||||||
|
|
||||||
// Run application
|
|
||||||
$app->run();
|
|
||||||
@ -1,75 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Create application
|
|
||||||
$app = new Application('Async Button Example', 800, 600);
|
|
||||||
|
|
||||||
// Create UI components
|
|
||||||
$container = new Container('flex flex-col p-4 gap-4');
|
|
||||||
|
|
||||||
// Status label to show loading state
|
|
||||||
$statusLabel = new Label(
|
|
||||||
text: 'Klicken Sie den Button, um Daten zu laden...',
|
|
||||||
style: 'text-base text-gray-700'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Result label to show fetched data
|
|
||||||
$resultLabel = new Label(
|
|
||||||
text: '',
|
|
||||||
style: 'text-sm text-blue-600'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Button with async onClick handler
|
|
||||||
$button = new Button(
|
|
||||||
text: 'Daten aus dem Web laden',
|
|
||||||
style: 'bg-blue-500 hover:bg-blue-700 text-white p-4 rounded-lg'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set async click handler
|
|
||||||
$button->setOnClickAsync(
|
|
||||||
// Task that runs in background thread
|
|
||||||
onClickAsync: function() {
|
|
||||||
// Simulate web request (or use real HTTP client)
|
|
||||||
sleep(2); // Simulates network delay
|
|
||||||
|
|
||||||
// In production, you would use something like:
|
|
||||||
// $response = file_get_contents('https://api.example.com/data');
|
|
||||||
// return json_decode($response, true);
|
|
||||||
|
|
||||||
return [
|
|
||||||
'status' => 'success',
|
|
||||||
'data' => 'Daten erfolgreich geladen!',
|
|
||||||
'timestamp' => date('H:i:s')
|
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
// Callback when task completes successfully
|
|
||||||
onComplete: function($result) use ($statusLabel, $resultLabel) {
|
|
||||||
$statusLabel->setText('✓ Laden abgeschlossen!');
|
|
||||||
$resultLabel->setText(
|
|
||||||
'Status: ' . $result['status'] . "\n" .
|
|
||||||
'Daten: ' . $result['data'] . "\n" .
|
|
||||||
'Zeit: ' . $result['timestamp']
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Callback when task fails
|
|
||||||
onError: function($error) use ($statusLabel, $resultLabel) {
|
|
||||||
$statusLabel->setText('✗ Fehler beim Laden!');
|
|
||||||
$resultLabel->setText('Error: ' . $error->getMessage());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add components to container
|
|
||||||
$container->addComponent($statusLabel);
|
|
||||||
$container->addComponent($button);
|
|
||||||
$container->addComponent($resultLabel);
|
|
||||||
|
|
||||||
// Set root component and run
|
|
||||||
$app->setRoot($container)->run();
|
|
||||||
@ -1,126 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Create application
|
|
||||||
$app = new Application('Async HTTP Request Example', 900, 700);
|
|
||||||
|
|
||||||
// Create UI
|
|
||||||
$container = new Container('flex flex-col p-6 gap-3 bg-gray-100');
|
|
||||||
|
|
||||||
$title = new Label(
|
|
||||||
text: 'Asynchrone HTTP Requests Demo',
|
|
||||||
style: 'text-2xl text-gray-900 mb-4'
|
|
||||||
);
|
|
||||||
|
|
||||||
$statusLabel = new Label(
|
|
||||||
text: 'Bereit zum Laden...',
|
|
||||||
style: 'text-base text-gray-700 p-2 bg-white rounded'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Button for fetching JSON data
|
|
||||||
$fetchButton = new Button(
|
|
||||||
text: 'JSON API abrufen',
|
|
||||||
style: 'bg-green-500 hover:bg-green-700 text-white p-3 rounded-lg'
|
|
||||||
);
|
|
||||||
|
|
||||||
$resultLabel = new Label(
|
|
||||||
text: '',
|
|
||||||
style: 'text-sm text-gray-800 p-3 bg-white rounded whitespace-pre-wrap'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set async handler for JSON fetch
|
|
||||||
$fetchButton->setOnClickAsync(
|
|
||||||
onClickAsync: function() {
|
|
||||||
// Fetch data from API (example: JSON placeholder)
|
|
||||||
$url = 'https://jsonplaceholder.typicode.com/todos/1';
|
|
||||||
|
|
||||||
$context = stream_context_create([
|
|
||||||
'http' => [
|
|
||||||
'timeout' => 10,
|
|
||||||
'method' => 'GET',
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response = @file_get_contents($url, false, $context);
|
|
||||||
|
|
||||||
if ($response === false) {
|
|
||||||
throw new \Exception('Failed to fetch data');
|
|
||||||
}
|
|
||||||
|
|
||||||
return json_decode($response, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
onComplete: function($data) use ($statusLabel, $resultLabel) {
|
|
||||||
$statusLabel->setText('✓ Daten erfolgreich geladen!');
|
|
||||||
|
|
||||||
$formatted = "ID: " . ($data['id'] ?? 'N/A') . "\n";
|
|
||||||
$formatted .= "Titel: " . ($data['title'] ?? 'N/A') . "\n";
|
|
||||||
$formatted .= "Erledigt: " . (($data['completed'] ?? false) ? 'Ja' : 'Nein');
|
|
||||||
|
|
||||||
$resultLabel->setText($formatted);
|
|
||||||
},
|
|
||||||
|
|
||||||
onError: function($error) use ($statusLabel, $resultLabel) {
|
|
||||||
$statusLabel->setText('✗ Fehler aufgetreten');
|
|
||||||
$resultLabel->setText('Error: ' . $error->getMessage());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Button for simulating slow operation
|
|
||||||
$slowButton = new Button(
|
|
||||||
text: 'Langsame Operation (5s)',
|
|
||||||
style: 'bg-orange-500 hover:bg-orange-700 text-white p-3 rounded-lg'
|
|
||||||
);
|
|
||||||
|
|
||||||
$slowButton->setOnClickAsync(
|
|
||||||
onClickAsync: function() {
|
|
||||||
$startTime = microtime(true);
|
|
||||||
|
|
||||||
// Simulate heavy computation
|
|
||||||
sleep(5);
|
|
||||||
|
|
||||||
$endTime = microtime(true);
|
|
||||||
$duration = round($endTime - $startTime, 2);
|
|
||||||
|
|
||||||
return [
|
|
||||||
'message' => 'Operation abgeschlossen',
|
|
||||||
'duration' => $duration . ' Sekunden'
|
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
onComplete: function($result) use ($statusLabel, $resultLabel) {
|
|
||||||
$statusLabel->setText('✓ Operation abgeschlossen!');
|
|
||||||
$resultLabel->setText(
|
|
||||||
$result['message'] . "\n" .
|
|
||||||
'Dauer: ' . $result['duration']
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
onError: function($error) use ($statusLabel, $resultLabel) {
|
|
||||||
$statusLabel->setText('✗ Fehler bei Operation');
|
|
||||||
$resultLabel->setText('Error: ' . $error->getMessage());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add all components
|
|
||||||
$container->addComponent($title);
|
|
||||||
$container->addComponent($statusLabel);
|
|
||||||
$container->addComponent($fetchButton);
|
|
||||||
$container->addComponent($slowButton);
|
|
||||||
$container->addComponent($resultLabel);
|
|
||||||
|
|
||||||
// Info label
|
|
||||||
$infoLabel = new Label(
|
|
||||||
text: 'Die UI bleibt während der Requests responsive!',
|
|
||||||
style: 'text-xs text-gray-500 mt-4 italic'
|
|
||||||
);
|
|
||||||
$container->addComponent($infoLabel);
|
|
||||||
|
|
||||||
// Run application
|
|
||||||
$app->setRoot($container)->run();
|
|
||||||
@ -1,160 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multi-Process Window Example
|
|
||||||
*
|
|
||||||
* Each window runs in a separate process (not thread!)
|
|
||||||
* This works because each process has its own main thread for OpenGL
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Check if we're the main process or a child
|
|
||||||
$windowId = $argv[1] ?? null;
|
|
||||||
|
|
||||||
if ($windowId === null) {
|
|
||||||
// MAIN PROCESS - Launch child processes
|
|
||||||
echo "Main Process: Launching 2 window processes...\n\n";
|
|
||||||
|
|
||||||
$pids = [];
|
|
||||||
|
|
||||||
// Launch Window 1 process
|
|
||||||
$pid1 = pcntl_fork();
|
|
||||||
if ($pid1 == -1) {
|
|
||||||
die("Could not fork for Window 1\n");
|
|
||||||
} elseif ($pid1 == 0) {
|
|
||||||
// Child process 1
|
|
||||||
runWindow('1', 'Window 1 - Blue', 100, 100, 'blue');
|
|
||||||
exit(0);
|
|
||||||
} else {
|
|
||||||
$pids[] = $pid1;
|
|
||||||
echo "Main Process: Window 1 started with PID $pid1\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Small delay to avoid race conditions
|
|
||||||
usleep(100000);
|
|
||||||
|
|
||||||
// Launch Window 2 process
|
|
||||||
$pid2 = pcntl_fork();
|
|
||||||
if ($pid2 == -1) {
|
|
||||||
die("Could not fork for Window 2\n");
|
|
||||||
} elseif ($pid2 == 0) {
|
|
||||||
// Child process 2
|
|
||||||
runWindow('2', 'Window 2 - Green', 550, 100, 'green');
|
|
||||||
exit(0);
|
|
||||||
} else {
|
|
||||||
$pids[] = $pid2;
|
|
||||||
echo "Main Process: Window 2 started with PID $pid2\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "\nMain Process: Both windows launched!\n";
|
|
||||||
echo "Main Process: Waiting for child processes to exit...\n\n";
|
|
||||||
|
|
||||||
// Wait for all child processes
|
|
||||||
foreach ($pids as $pid) {
|
|
||||||
$status = 0;
|
|
||||||
pcntl_waitpid($pid, $status);
|
|
||||||
echo "Main Process: Child process $pid exited\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "\nMain Process: All windows closed. Exiting.\n";
|
|
||||||
} else {
|
|
||||||
// This shouldn't happen in fork mode
|
|
||||||
die("Error: Unexpected command line argument\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run a single window in this process
|
|
||||||
*/
|
|
||||||
function runWindow(string $id, string $title, int $x, int $y, string $bgColor): void
|
|
||||||
{
|
|
||||||
echo "Process $id: Creating window '$title'\n";
|
|
||||||
|
|
||||||
// Create application
|
|
||||||
$app = new Application();
|
|
||||||
|
|
||||||
// Create window
|
|
||||||
$window = $app->createWindow($title, 400, 350, $x, $y);
|
|
||||||
|
|
||||||
// Create UI
|
|
||||||
$container = new Container("flex flex-col p-6 gap-4 bg-$bgColor-100");
|
|
||||||
|
|
||||||
$titleLabel = new Label(
|
|
||||||
text: $title,
|
|
||||||
style: "text-2xl text-$bgColor-900"
|
|
||||||
);
|
|
||||||
|
|
||||||
$processLabel = new Label(
|
|
||||||
text: 'Process ID: ' . getmypid(),
|
|
||||||
style: "text-sm text-$bgColor-700"
|
|
||||||
);
|
|
||||||
|
|
||||||
$frameLabel = new Label(
|
|
||||||
text: 'Frame: 0',
|
|
||||||
style: "text-base text-$bgColor-600"
|
|
||||||
);
|
|
||||||
|
|
||||||
$button = new Button(
|
|
||||||
text: 'Click Me!',
|
|
||||||
style: "bg-$bgColor-500 hover:bg-$bgColor-700 text-white p-4 rounded-lg"
|
|
||||||
);
|
|
||||||
|
|
||||||
$clickCount = 0;
|
|
||||||
$button->setOnClick(function() use (&$clickCount, $button, $title) {
|
|
||||||
$clickCount++;
|
|
||||||
$button->setText("Clicked $clickCount times");
|
|
||||||
echo "$title - Button clicked! Count: $clickCount\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
$closeButton = new Button(
|
|
||||||
text: 'Close Window',
|
|
||||||
style: "bg-red-500 hover:bg-red-700 text-white p-3 rounded"
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton->setOnClick(function() use ($window) {
|
|
||||||
echo "Close button clicked!\n";
|
|
||||||
$window->close();
|
|
||||||
});
|
|
||||||
|
|
||||||
$container->addComponent($titleLabel);
|
|
||||||
$container->addComponent($processLabel);
|
|
||||||
$container->addComponent($frameLabel);
|
|
||||||
$container->addComponent($button);
|
|
||||||
$container->addComponent($closeButton);
|
|
||||||
|
|
||||||
$window->setRoot($container);
|
|
||||||
|
|
||||||
echo "Process $id: Starting event loop\n";
|
|
||||||
|
|
||||||
// Run the window
|
|
||||||
$frameCount = 0;
|
|
||||||
while (!$window->shouldClose()) {
|
|
||||||
$frameCount++;
|
|
||||||
$frameLabel->setText("Frame: $frameCount");
|
|
||||||
|
|
||||||
$window->layout();
|
|
||||||
|
|
||||||
// Poll events
|
|
||||||
rgfw_pollEvents();
|
|
||||||
$window->handleEvents();
|
|
||||||
|
|
||||||
// Update
|
|
||||||
\PHPNative\Async\TaskManager::getInstance()->update();
|
|
||||||
$window->update();
|
|
||||||
|
|
||||||
// Render
|
|
||||||
$window->render();
|
|
||||||
|
|
||||||
// ~60 FPS
|
|
||||||
usleep(16666);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
echo "Process $id: Window closed after $frameCount frames\n";
|
|
||||||
$window->cleanup();
|
|
||||||
}
|
|
||||||
@ -1,161 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Create application
|
|
||||||
$app = new Application();
|
|
||||||
|
|
||||||
// Create main window
|
|
||||||
$mainWindow = $app->createWindow('Main Window - Multi-Window Demo', 600, 400, 100, 100);
|
|
||||||
|
|
||||||
// Counter for new windows
|
|
||||||
$windowCounter = 1;
|
|
||||||
|
|
||||||
// Create main window UI
|
|
||||||
$mainContainer = new Container('flex flex-col p-6 gap-4 bg-gray-100');
|
|
||||||
|
|
||||||
$title = new Label(
|
|
||||||
text: 'Multi-Window Demo',
|
|
||||||
style: 'text-2xl text-gray-900'
|
|
||||||
);
|
|
||||||
|
|
||||||
$description = new Label(
|
|
||||||
text: 'Klicken Sie auf die Buttons, um neue Windows zu erstellen!',
|
|
||||||
style: 'text-base text-gray-700'
|
|
||||||
);
|
|
||||||
|
|
||||||
$windowCountLabel = new Label(
|
|
||||||
text: 'Offene Windows: 1',
|
|
||||||
style: 'text-sm text-blue-600 p-2 bg-white rounded'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Button to create a simple new window
|
|
||||||
$createSimpleButton = new Button(
|
|
||||||
text: 'Neues Fenster erstellen',
|
|
||||||
style: 'bg-blue-500 hover:bg-blue-700 text-white p-4 rounded-lg'
|
|
||||||
);
|
|
||||||
|
|
||||||
$createSimpleButton->setOnClick(function() use ($app, &$windowCounter, $windowCountLabel) {
|
|
||||||
// Create new window with offset position
|
|
||||||
$offset = $windowCounter * 30;
|
|
||||||
$newWindow = $app->createWindow(
|
|
||||||
"Window #$windowCounter",
|
|
||||||
500,
|
|
||||||
300,
|
|
||||||
150 + $offset,
|
|
||||||
150 + $offset
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create UI for new window
|
|
||||||
$container = new Container('flex flex-col p-6 gap-3 bg-gradient-to-br from-purple-400 to-pink-400');
|
|
||||||
|
|
||||||
$label = new Label(
|
|
||||||
text: "Dies ist Window #$windowCounter",
|
|
||||||
style: 'text-xl text-white'
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton = new Button(
|
|
||||||
text: 'Fenster schließen',
|
|
||||||
style: 'bg-red-500 hover:bg-red-700 text-white p-3 rounded'
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton->setOnClick(function() use ($newWindow) {
|
|
||||||
$newWindow->close();
|
|
||||||
});
|
|
||||||
|
|
||||||
$container->addComponent($label);
|
|
||||||
$container->addComponent($closeButton);
|
|
||||||
$newWindow->setRoot($container);
|
|
||||||
|
|
||||||
$windowCounter++;
|
|
||||||
|
|
||||||
// Update counter
|
|
||||||
$windowCountLabel->setText('Offene Windows: ' . $app->getWindowCount());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Button to create a window with interactive content
|
|
||||||
$createInteractiveButton = new Button(
|
|
||||||
text: 'Interaktives Fenster erstellen',
|
|
||||||
style: 'bg-green-500 hover:bg-green-700 text-white p-4 rounded-lg'
|
|
||||||
);
|
|
||||||
|
|
||||||
$createInteractiveButton->setOnClick(function() use ($app, &$windowCounter, $windowCountLabel) {
|
|
||||||
$offset = $windowCounter * 30;
|
|
||||||
$newWindow = $app->createWindow(
|
|
||||||
"Interactive Window #$windowCounter",
|
|
||||||
600,
|
|
||||||
400,
|
|
||||||
150 + $offset,
|
|
||||||
150 + $offset
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create interactive UI
|
|
||||||
$container = new Container('flex flex-col p-6 gap-3 bg-blue-50');
|
|
||||||
|
|
||||||
$title = new Label(
|
|
||||||
text: "Interaktives Window #$windowCounter",
|
|
||||||
style: 'text-xl text-gray-900'
|
|
||||||
);
|
|
||||||
|
|
||||||
$counter = 0;
|
|
||||||
$counterLabel = new Label(
|
|
||||||
text: "Zähler: $counter",
|
|
||||||
style: 'text-lg text-blue-600 p-2 bg-white rounded'
|
|
||||||
);
|
|
||||||
|
|
||||||
$incrementButton = new Button(
|
|
||||||
text: 'Zähler erhöhen',
|
|
||||||
style: 'bg-blue-500 hover:bg-blue-700 text-white p-3 rounded'
|
|
||||||
);
|
|
||||||
|
|
||||||
$incrementButton->setOnClick(function() use (&$counter, $counterLabel) {
|
|
||||||
$counter++;
|
|
||||||
$counterLabel->setText("Zähler: $counter");
|
|
||||||
});
|
|
||||||
|
|
||||||
$closeButton = new Button(
|
|
||||||
text: 'Fenster schließen',
|
|
||||||
style: 'bg-red-500 hover:bg-red-700 text-white p-3 rounded'
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton->setOnClick(function() use ($newWindow) {
|
|
||||||
$newWindow->close();
|
|
||||||
});
|
|
||||||
|
|
||||||
$container->addComponent($title);
|
|
||||||
$container->addComponent($counterLabel);
|
|
||||||
$container->addComponent($incrementButton);
|
|
||||||
$container->addComponent($closeButton);
|
|
||||||
$newWindow->setRoot($container);
|
|
||||||
|
|
||||||
$windowCounter++;
|
|
||||||
$windowCountLabel->setText('Offene Windows: ' . $app->getWindowCount());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Button to quit application
|
|
||||||
$quitButton = new Button(
|
|
||||||
text: 'Alle Fenster schließen und beenden',
|
|
||||||
style: 'bg-red-600 hover:bg-red-800 text-white p-4 rounded-lg mt-4'
|
|
||||||
);
|
|
||||||
|
|
||||||
$quitButton->setOnClick(function() use ($app) {
|
|
||||||
$app->quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add all components to main container
|
|
||||||
$mainContainer->addComponent($title);
|
|
||||||
$mainContainer->addComponent($description);
|
|
||||||
$mainContainer->addComponent($windowCountLabel);
|
|
||||||
$mainContainer->addComponent($createSimpleButton);
|
|
||||||
$mainContainer->addComponent($createInteractiveButton);
|
|
||||||
$mainContainer->addComponent($quitButton);
|
|
||||||
|
|
||||||
$mainWindow->setRoot($mainContainer);
|
|
||||||
|
|
||||||
// Run application
|
|
||||||
$app->run();
|
|
||||||
@ -1,135 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// Enable event debugging (optional - set to false to disable)
|
|
||||||
define('DEBUG_EVENTS', true);
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
echo "Starting two-window test application...\n";
|
|
||||||
echo 'DEBUG_EVENTS: ' . (DEBUG_EVENTS ? 'enabled' : 'disabled') . "\n";
|
|
||||||
|
|
||||||
// Create application
|
|
||||||
$app = new Application();
|
|
||||||
|
|
||||||
// Frame counter for window 1
|
|
||||||
$window1FrameCount = 0;
|
|
||||||
|
|
||||||
echo "Creating Window 1...\n";
|
|
||||||
$window1 = $app->createWindow('Window 1', 400, 300, 100, 100);
|
|
||||||
$container1 = new Container('flex flex-col p-6 gap-4 bg-blue-100');
|
|
||||||
|
|
||||||
$title1 = new Label(
|
|
||||||
text: 'Window 1',
|
|
||||||
style: 'text-2xl text-blue-900',
|
|
||||||
);
|
|
||||||
|
|
||||||
$frameLabel1 = new Label(
|
|
||||||
text: 'Frame: 0',
|
|
||||||
style: 'text-base text-blue-700',
|
|
||||||
);
|
|
||||||
|
|
||||||
$button1 = new Button(
|
|
||||||
text: 'Click Me (Window 1)',
|
|
||||||
style: 'bg-blue-500 hover:bg-blue-700 text-white p-4 rounded',
|
|
||||||
);
|
|
||||||
|
|
||||||
$clickCount1 = 0;
|
|
||||||
$button1->setOnClick(function () use (&$clickCount1, $button1) {
|
|
||||||
$clickCount1++;
|
|
||||||
$button1->setText("Clicked {$clickCount1} times");
|
|
||||||
echo "Window 1 button clicked! Count: {$clickCount1}\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
$container1->addComponent($title1);
|
|
||||||
$container1->addComponent($frameLabel1);
|
|
||||||
$container1->addComponent($button1);
|
|
||||||
$window1->setRoot($container1);
|
|
||||||
|
|
||||||
// Frame counter for window 2
|
|
||||||
$window2FrameCount = 0;
|
|
||||||
|
|
||||||
echo "Creating Window 2...\n";
|
|
||||||
$window2 = $app->createWindow('Window 2', 400, 300, 520, 100);
|
|
||||||
$container2 = new Container('flex flex-col p-6 gap-4 bg-green-100');
|
|
||||||
|
|
||||||
$title2 = new Label(
|
|
||||||
text: 'Window 2',
|
|
||||||
style: 'text-2xl text-green-900',
|
|
||||||
);
|
|
||||||
|
|
||||||
$frameLabel2 = new Label(
|
|
||||||
text: 'Frame: 0',
|
|
||||||
style: 'text-base text-green-700',
|
|
||||||
);
|
|
||||||
|
|
||||||
$button2 = new Button(
|
|
||||||
text: 'Click Me (Window 2)',
|
|
||||||
style: 'bg-green-500 hover:bg-green-700 text-white p-4 rounded',
|
|
||||||
);
|
|
||||||
|
|
||||||
$clickCount2 = 0;
|
|
||||||
$button2->setOnClick(function () use (&$clickCount2, $button2) {
|
|
||||||
$clickCount2++;
|
|
||||||
$button2->setText("Clicked {$clickCount2} times");
|
|
||||||
echo "Window 2 button clicked! Count: {$clickCount2}\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
$container2->addComponent($title2);
|
|
||||||
$container2->addComponent($frameLabel2);
|
|
||||||
$container2->addComponent($button2);
|
|
||||||
$window2->setRoot($container2);
|
|
||||||
|
|
||||||
echo "Starting main loop...\n";
|
|
||||||
echo "Click the buttons to test interaction!\n";
|
|
||||||
echo "Close all windows to exit.\n\n";
|
|
||||||
|
|
||||||
// Custom run loop with frame counter updates
|
|
||||||
$running = true;
|
|
||||||
while ($running && count($app->getWindows()) > 0) {
|
|
||||||
// Update frame counters
|
|
||||||
$window1FrameCount++;
|
|
||||||
$window2FrameCount++;
|
|
||||||
$frameLabel1->setText("Frame: {$window1FrameCount}");
|
|
||||||
$frameLabel2->setText("Frame: {$window2FrameCount}");
|
|
||||||
|
|
||||||
// Layout all windows FIRST (sets window references and calculates positions)
|
|
||||||
foreach ($app->getWindows() as $windowId => $window) {
|
|
||||||
$window->layout();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle events for all windows (now that layout is done)
|
|
||||||
foreach ($app->getWindows() as $windowId => $window) {
|
|
||||||
$window->handleEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update async tasks (global)
|
|
||||||
PHPNative\Async\TaskManager::getInstance()->update();
|
|
||||||
|
|
||||||
// Update all windows
|
|
||||||
foreach ($app->getWindows() as $windowId => $window) {
|
|
||||||
$window->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render all windows
|
|
||||||
foreach ($app->getWindows() as $windowId => $window) {
|
|
||||||
$window->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove closed windows
|
|
||||||
$windowsCopy = $app->getWindows();
|
|
||||||
foreach ($windowsCopy as $windowId => $window) {
|
|
||||||
if ($window->shouldClose()) {
|
|
||||||
echo "Window {$windowId} closing...\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit frame rate to ~60 FPS
|
|
||||||
usleep(16666);
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Application exited.\n";
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Create application
|
|
||||||
$app = new Application();
|
|
||||||
|
|
||||||
// Create a single window (simple usage)
|
|
||||||
$window = $app->createWindow('Simple Window Example', 800, 600);
|
|
||||||
|
|
||||||
// Create UI
|
|
||||||
$container = new Container('flex flex-col p-6 gap-4 bg-gradient-to-br from-blue-400 to-purple-500');
|
|
||||||
|
|
||||||
$title = new Label(
|
|
||||||
text: 'Willkommen zu PHPNative!',
|
|
||||||
style: 'text-3xl text-white'
|
|
||||||
);
|
|
||||||
|
|
||||||
$description = new Label(
|
|
||||||
text: 'Dies ist ein einfaches Beispiel mit einem Window.',
|
|
||||||
style: 'text-lg text-white'
|
|
||||||
);
|
|
||||||
|
|
||||||
$button = new Button(
|
|
||||||
text: 'Klick mich!',
|
|
||||||
style: 'bg-white hover:bg-gray-100 text-blue-600 p-4 rounded-lg'
|
|
||||||
);
|
|
||||||
|
|
||||||
$statusLabel = new Label(
|
|
||||||
text: '',
|
|
||||||
style: 'text-base text-white'
|
|
||||||
);
|
|
||||||
|
|
||||||
$clickCount = 0;
|
|
||||||
$button->setOnClick(function() use ($statusLabel, &$clickCount) {
|
|
||||||
$clickCount++;
|
|
||||||
$statusLabel->setText("Button wurde $clickCount mal geklickt!");
|
|
||||||
});
|
|
||||||
|
|
||||||
$quitButton = new Button(
|
|
||||||
text: 'Beenden',
|
|
||||||
style: 'bg-red-500 hover:bg-red-700 text-white p-4 rounded-lg mt-4'
|
|
||||||
);
|
|
||||||
|
|
||||||
$quitButton->setOnClick(function() use ($app) {
|
|
||||||
$app->quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add components
|
|
||||||
$container->addComponent($title);
|
|
||||||
$container->addComponent($description);
|
|
||||||
$container->addComponent($button);
|
|
||||||
$container->addComponent($statusLabel);
|
|
||||||
$container->addComponent($quitButton);
|
|
||||||
|
|
||||||
// Set window root
|
|
||||||
$window->setRoot($container);
|
|
||||||
|
|
||||||
// Run application
|
|
||||||
$app->run();
|
|
||||||
42
examples/test_flex_col.php
Normal file
42
examples/test_flex_col.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use PHPNative\Framework\Application;
|
||||||
|
use PHPNative\Ui\Window;
|
||||||
|
use PHPNative\Ui\Widget\Container;
|
||||||
|
use PHPNative\Ui\Widget\Label;
|
||||||
|
|
||||||
|
$app = new Application();
|
||||||
|
$window = new Window('Flex-Col Test', 800, 600);
|
||||||
|
|
||||||
|
// Main container mit flex-col
|
||||||
|
$mainContainer = new Container('flex flex-col p-4 bg-gray-100');
|
||||||
|
|
||||||
|
// Container 1 - Feste Höhe
|
||||||
|
$container1 = new Container('bg-red-500 h-20 p-4');
|
||||||
|
$label1 = new Label('Container 1 - Fixed Height (h-20)', 'text-white text-xl');
|
||||||
|
$container1->addComponent($label1);
|
||||||
|
$mainContainer->addComponent($container1);
|
||||||
|
|
||||||
|
// Container 2 - Mit flex-grow (sollte verfügbaren Platz einnehmen)
|
||||||
|
$container2 = new Container('flex-grow bg-blue-500 p-4');
|
||||||
|
$label2 = new Label('Container 2 - Flex Grow (flex-grow)', 'text-white text-xl');
|
||||||
|
$container2->addComponent($label2);
|
||||||
|
$mainContainer->addComponent($container2);
|
||||||
|
|
||||||
|
// Container 3 - Natürliche Höhe (basierend auf Inhalt)
|
||||||
|
$container3 = new Container('bg-green-500 p-4');
|
||||||
|
$label3 = new Label('Container 3 - Natural Height', 'text-white text-xl');
|
||||||
|
$container3->addComponent($label3);
|
||||||
|
$mainContainer->addComponent($container3);
|
||||||
|
|
||||||
|
$window->setRoot($mainContainer);
|
||||||
|
$app->addWindow($window);
|
||||||
|
|
||||||
|
echo "Flex-Col Test started!\n";
|
||||||
|
echo "- Red: Fixed height (80px)\n";
|
||||||
|
echo "- Blue: Should grow to fill available space\n";
|
||||||
|
echo "- Green: Natural height based on content\n\n";
|
||||||
|
|
||||||
|
$app->run();
|
||||||
47
examples/test_textinput.php
Normal file
47
examples/test_textinput.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use PHPNative\Framework\Application;
|
||||||
|
use PHPNative\Ui\Widget\Button;
|
||||||
|
use PHPNative\Ui\Widget\Container;
|
||||||
|
use PHPNative\Ui\Widget\TextInput;
|
||||||
|
use PHPNative\Ui\Window;
|
||||||
|
|
||||||
|
$app = new Application();
|
||||||
|
$window = new Window('TextInput Test', 600, 400);
|
||||||
|
|
||||||
|
// Main container
|
||||||
|
$mainContainer = new Container('flex flex-col p-4 bg-gray-100');
|
||||||
|
|
||||||
|
// Container 1 - Red background mit fester Höhe
|
||||||
|
$container1 = new Container('bg-red-500 h-20 mb-4 p-2');
|
||||||
|
$mainContainer->addComponent($container1);
|
||||||
|
|
||||||
|
// Container 2 - Mit TextInput und Button (flex-row)
|
||||||
|
$inputContainer = new Container('flex flex-row mb-4 bg-blue-200');
|
||||||
|
|
||||||
|
$input = new TextInput(
|
||||||
|
placeholder: 'Type something...',
|
||||||
|
style: 'flex-1 p-2 border border-gray-300 rounded mr-2 h-10',
|
||||||
|
);
|
||||||
|
|
||||||
|
$button = new Button('Submit', 'bg-green-500 text-white p-2 rounded');
|
||||||
|
|
||||||
|
$inputContainer->addComponent($input);
|
||||||
|
$inputContainer->addComponent($button);
|
||||||
|
$mainContainer->addComponent($inputContainer);
|
||||||
|
|
||||||
|
// Container 3 - Green background mit fester Höhe
|
||||||
|
$container3 = new Container('bg-green-500 h-20 p-2');
|
||||||
|
$mainContainer->addComponent($container3);
|
||||||
|
|
||||||
|
$window->setRoot($mainContainer);
|
||||||
|
$app->addWindow($window);
|
||||||
|
|
||||||
|
echo "TextInput Test started!\n";
|
||||||
|
echo "- Red container (80px)\n";
|
||||||
|
echo "- Blue container with TextInput and Button (40px)\n";
|
||||||
|
echo "- Green container (80px)\n\n";
|
||||||
|
|
||||||
|
$app->run();
|
||||||
39
examples/test_textinput_simple.php
Normal file
39
examples/test_textinput_simple.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use PHPNative\Framework\Application;
|
||||||
|
use PHPNative\Ui\Widget\Button;
|
||||||
|
use PHPNative\Ui\Widget\Container;
|
||||||
|
use PHPNative\Ui\Widget\TextInput;
|
||||||
|
use PHPNative\Ui\Window;
|
||||||
|
|
||||||
|
$app = new Application();
|
||||||
|
$window = new Window('TextInput Test', 600, 400);
|
||||||
|
|
||||||
|
// Main container
|
||||||
|
$mainContainer = new Container('flex flex-col p-4 bg-gray-100');
|
||||||
|
|
||||||
|
// Container 2 - Mit TextInput und Button (flex-row)
|
||||||
|
$inputContainer = new Container('flex flex-row p-4 g-blue-200');
|
||||||
|
|
||||||
|
$input = new TextInput(
|
||||||
|
placeholder: 'Type something...',
|
||||||
|
style: 'flex-1 p-2 border border-gray-300 rounded mr-2',
|
||||||
|
);
|
||||||
|
|
||||||
|
$button = new Button('Submit', 'bg-green-500 text-white p-2 rounded-xl');
|
||||||
|
|
||||||
|
$inputContainer->addComponent($input);
|
||||||
|
$inputContainer->addComponent($button);
|
||||||
|
$mainContainer->addComponent($inputContainer);
|
||||||
|
|
||||||
|
$window->setRoot($mainContainer);
|
||||||
|
$app->addWindow($window);
|
||||||
|
|
||||||
|
echo "TextInput Test started!\n";
|
||||||
|
echo "- Red container (80px)\n";
|
||||||
|
echo "- Blue container with TextInput and Button (40px)\n";
|
||||||
|
echo "- Green container (80px)\n\n";
|
||||||
|
|
||||||
|
$app->run();
|
||||||
@ -1,153 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example with 2 framework windows running in parallel threads
|
|
||||||
* Requires: parallel extension
|
|
||||||
*
|
|
||||||
* Note: Each window runs in its own thread with its own event loop
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use parallel\Runtime;
|
|
||||||
use PHPNative\Framework\Application;
|
|
||||||
use PHPNative\Ui\Widget\Button;
|
|
||||||
use PHPNative\Ui\Widget\Container;
|
|
||||||
use PHPNative\Ui\Widget\Label;
|
|
||||||
|
|
||||||
// Check if parallel extension is loaded
|
|
||||||
if (!extension_loaded('parallel')) {
|
|
||||||
die("Error: parallel extension is not loaded. Install with: pecl install parallel\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Starting 2 framework windows in parallel threads...\n\n";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to run a window with the framework in a thread
|
|
||||||
*/
|
|
||||||
$windowRunner = function(string $title, int $x, int $y, string $bgColor) {
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
// Create application for this thread
|
|
||||||
$app = new \PHPNative\Framework\Application();
|
|
||||||
|
|
||||||
// Create window
|
|
||||||
$window = $app->createWindow($title, 400, 350, $x, $y);
|
|
||||||
|
|
||||||
// Create UI
|
|
||||||
$container = new \PHPNative\Ui\Widget\Container("flex flex-col p-6 gap-4 bg-$bgColor-100");
|
|
||||||
|
|
||||||
$titleLabel = new \PHPNative\Ui\Widget\Label(
|
|
||||||
text: $title,
|
|
||||||
style: "text-2xl text-$bgColor-900"
|
|
||||||
);
|
|
||||||
|
|
||||||
$infoLabel = new \PHPNative\Ui\Widget\Label(
|
|
||||||
text: 'Running in separate thread',
|
|
||||||
style: "text-sm text-$bgColor-700"
|
|
||||||
);
|
|
||||||
|
|
||||||
$frameLabel = new \PHPNative\Ui\Widget\Label(
|
|
||||||
text: 'Frame: 0',
|
|
||||||
style: "text-base text-$bgColor-600"
|
|
||||||
);
|
|
||||||
|
|
||||||
$button = new \PHPNative\Ui\Widget\Button(
|
|
||||||
text: 'Click Me!',
|
|
||||||
style: "bg-$bgColor-500 hover:bg-$bgColor-700 text-white p-4 rounded-lg"
|
|
||||||
);
|
|
||||||
|
|
||||||
$clickCount = 0;
|
|
||||||
$button->setOnClick(function() use (&$clickCount, $button, $title) {
|
|
||||||
$clickCount++;
|
|
||||||
$button->setText("Clicked $clickCount times");
|
|
||||||
echo "$title - Button clicked! Count: $clickCount\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
$closeButton = new \PHPNative\Ui\Widget\Button(
|
|
||||||
text: 'Close Window',
|
|
||||||
style: "bg-red-500 hover:bg-red-700 text-white p-3 rounded"
|
|
||||||
);
|
|
||||||
|
|
||||||
$closeButton->setOnClick(function() use ($window) {
|
|
||||||
$window->close();
|
|
||||||
});
|
|
||||||
|
|
||||||
$container->addComponent($titleLabel);
|
|
||||||
$container->addComponent($infoLabel);
|
|
||||||
$container->addComponent($frameLabel);
|
|
||||||
$container->addComponent($button);
|
|
||||||
$container->addComponent($closeButton);
|
|
||||||
|
|
||||||
$window->setRoot($container);
|
|
||||||
|
|
||||||
// Custom run loop with frame counter
|
|
||||||
$frameCount = 0;
|
|
||||||
while (!$window->shouldClose()) {
|
|
||||||
$frameCount++;
|
|
||||||
$frameLabel->setText("Frame: $frameCount");
|
|
||||||
|
|
||||||
$window->layout();
|
|
||||||
|
|
||||||
// Poll events
|
|
||||||
rgfw_pollEvents();
|
|
||||||
$window->handleEvents();
|
|
||||||
|
|
||||||
// Update
|
|
||||||
\PHPNative\Async\TaskManager::getInstance()->update();
|
|
||||||
$window->update();
|
|
||||||
|
|
||||||
// Render
|
|
||||||
$window->render();
|
|
||||||
|
|
||||||
// ~60 FPS
|
|
||||||
usleep(16666);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
$window->cleanup();
|
|
||||||
|
|
||||||
return "$title closed after $frameCount frames";
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Launch Window 1 (Blue) in thread
|
|
||||||
echo "Launching Window 1 (Blue) in thread...\n";
|
|
||||||
$runtime1 = new Runtime();
|
|
||||||
$future1 = $runtime1->run($windowRunner, [
|
|
||||||
'Window 1 - Blue',
|
|
||||||
100,
|
|
||||||
100,
|
|
||||||
'blue'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Launch Window 2 (Green) in thread
|
|
||||||
echo "Launching Window 2 (Green) in thread...\n";
|
|
||||||
$runtime2 = new Runtime();
|
|
||||||
$future2 = $runtime2->run($windowRunner, [
|
|
||||||
'Window 2 - Green',
|
|
||||||
550,
|
|
||||||
100,
|
|
||||||
'green'
|
|
||||||
]);
|
|
||||||
|
|
||||||
echo "\nBoth windows launched in parallel threads!\n";
|
|
||||||
echo "Each window has its own event loop\n";
|
|
||||||
echo "Try clicking the buttons and closing windows\n";
|
|
||||||
echo "Main thread waiting for windows to close...\n\n";
|
|
||||||
|
|
||||||
// Wait for both windows to complete
|
|
||||||
echo "Waiting for Window 1...\n";
|
|
||||||
$result1 = $future1->value();
|
|
||||||
echo $result1 . "\n";
|
|
||||||
|
|
||||||
echo "Waiting for Window 2...\n";
|
|
||||||
$result2 = $future2->value();
|
|
||||||
echo $result2 . "\n";
|
|
||||||
|
|
||||||
echo "\nAll windows closed. Application exiting.\n";
|
|
||||||
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
echo "Error: " . $e->getMessage() . "\n";
|
|
||||||
echo "Stack trace:\n" . $e->getTraceAsString() . "\n";
|
|
||||||
}
|
|
||||||
@ -1,170 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple example with 2 windows running in parallel threads
|
|
||||||
* Requires: parallel extension
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use parallel\Runtime;
|
|
||||||
use parallel\Channel;
|
|
||||||
|
|
||||||
// Check if parallel extension is loaded
|
|
||||||
if (!extension_loaded('parallel')) {
|
|
||||||
die("Error: parallel extension is not loaded. Install with: pecl install parallel\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Starting 2 windows in parallel threads...\n";
|
|
||||||
echo "Each window runs independently in its own thread\n";
|
|
||||||
echo "Press ESC or close button to exit each window\n\n";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Window function that runs in a thread
|
|
||||||
*/
|
|
||||||
$windowFunction = function(string $title, int $x, int $y, int $width, int $height, array $bgColor) {
|
|
||||||
// Enable event queue mode
|
|
||||||
rgfw_setQueueEvents(true);
|
|
||||||
|
|
||||||
// Create window
|
|
||||||
$window = rgfw_createWindow($title, $x, $y, $width, $height, 0);
|
|
||||||
if (!$window) {
|
|
||||||
throw new \Exception("Failed to create window: $title");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize RSGL renderer
|
|
||||||
if (!rsgl_init($window)) {
|
|
||||||
throw new \Exception("Failed to initialize RSGL for: $title");
|
|
||||||
}
|
|
||||||
|
|
||||||
[$r, $g, $b] = $bgColor;
|
|
||||||
$running = true;
|
|
||||||
$frameCount = 0;
|
|
||||||
$mouseX = 0;
|
|
||||||
$mouseY = 0;
|
|
||||||
$isHovering = false;
|
|
||||||
|
|
||||||
while ($running) {
|
|
||||||
// Poll events for this window
|
|
||||||
rgfw_pollEvents();
|
|
||||||
|
|
||||||
// Process queued events
|
|
||||||
while ($event = rgfw_window_checkQueuedEvent($window)) {
|
|
||||||
switch ($event['type']) {
|
|
||||||
case RGFW_quit:
|
|
||||||
$running = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RGFW_keyPressed:
|
|
||||||
$keyCode = $event['keyCode'] ?? 0;
|
|
||||||
if ($keyCode == RGFW_Escape) {
|
|
||||||
$running = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RGFW_mousePosChanged:
|
|
||||||
$mouseX = $event[0] ?? 0;
|
|
||||||
$mouseY = $event[1] ?? 0;
|
|
||||||
|
|
||||||
// Check if hovering over center rectangle
|
|
||||||
$rectSize = 100;
|
|
||||||
$rectX = ($width / 2) - ($rectSize / 2);
|
|
||||||
$rectY = ($height / 2) - ($rectSize / 2);
|
|
||||||
|
|
||||||
$isHovering = $mouseX >= $rectX && $mouseX <= ($rectX + $rectSize) &&
|
|
||||||
$mouseY >= $rectY && $mouseY <= ($rectY + $rectSize);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RGFW_mouseButtonPressed:
|
|
||||||
if ($isHovering) {
|
|
||||||
echo "$title - Rectangle clicked!\n";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window should close
|
|
||||||
if (rgfw_window_shouldClose($window)) {
|
|
||||||
$running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear with background color
|
|
||||||
rsgl_clear($window, $r, $g, $b, 255);
|
|
||||||
|
|
||||||
// Draw center rectangle
|
|
||||||
$rectSize = 100;
|
|
||||||
$rectX = ($width / 2) - ($rectSize / 2);
|
|
||||||
$rectY = ($height / 2) - ($rectSize / 2);
|
|
||||||
|
|
||||||
// White or yellow depending on hover state
|
|
||||||
if ($isHovering) {
|
|
||||||
rsgl_setColor($window, 255, 255, 100, 255); // Yellow on hover
|
|
||||||
} else {
|
|
||||||
rsgl_setColor($window, 255, 255, 255, 255); // White
|
|
||||||
}
|
|
||||||
rsgl_drawRectF($window, (int) $rectX, (int) $rectY, $rectSize, $rectSize);
|
|
||||||
|
|
||||||
// Draw text showing frame count (if possible)
|
|
||||||
$frameCount++;
|
|
||||||
|
|
||||||
// Render and swap buffers
|
|
||||||
rsgl_render($window);
|
|
||||||
rgfw_window_swapBuffers($window);
|
|
||||||
|
|
||||||
// ~60 FPS
|
|
||||||
usleep(16666);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
rsgl_close($window);
|
|
||||||
rgfw_window_close($window);
|
|
||||||
|
|
||||||
return "$title closed after $frameCount frames";
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Create first window in a thread (Red background)
|
|
||||||
echo "Launching Window 1 (Red) in thread...\n";
|
|
||||||
$runtime1 = new Runtime();
|
|
||||||
$future1 = $runtime1->run($windowFunction, [
|
|
||||||
'Window 1 - Red',
|
|
||||||
100,
|
|
||||||
100,
|
|
||||||
400,
|
|
||||||
300,
|
|
||||||
[255, 100, 100]
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Create second window in a thread (Blue background)
|
|
||||||
echo "Launching Window 2 (Blue) in thread...\n";
|
|
||||||
$runtime2 = new Runtime();
|
|
||||||
$future2 = $runtime2->run($windowFunction, [
|
|
||||||
'Window 2 - Blue',
|
|
||||||
550,
|
|
||||||
100,
|
|
||||||
400,
|
|
||||||
300,
|
|
||||||
[100, 100, 255]
|
|
||||||
]);
|
|
||||||
|
|
||||||
echo "\nBoth windows launched!\n";
|
|
||||||
echo "Hover over the center rectangles to see them change color\n";
|
|
||||||
echo "Click on them to see messages in the console\n";
|
|
||||||
echo "Main thread waiting for windows to close...\n\n";
|
|
||||||
|
|
||||||
// Wait for first window
|
|
||||||
echo "Waiting for Window 1...\n";
|
|
||||||
$result1 = $future1->value();
|
|
||||||
echo $result1 . "\n";
|
|
||||||
|
|
||||||
// Wait for second window
|
|
||||||
echo "Waiting for Window 2...\n";
|
|
||||||
$result2 = $future2->value();
|
|
||||||
echo $result2 . "\n";
|
|
||||||
|
|
||||||
echo "\nAll windows closed. Application exiting.\n";
|
|
||||||
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
echo "Error: " . $e->getMessage() . "\n";
|
|
||||||
echo "Stack trace:\n" . $e->getTraceAsString() . "\n";
|
|
||||||
}
|
|
||||||
129
examples/todo_app.php
Normal file
129
examples/todo_app.php
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use PHPNative\Framework\Application;
|
||||||
|
use PHPNative\Ui\Widget\Button;
|
||||||
|
use PHPNative\Ui\Widget\Checkbox;
|
||||||
|
use PHPNative\Ui\Widget\Container;
|
||||||
|
use PHPNative\Ui\Widget\Label;
|
||||||
|
use PHPNative\Ui\Widget\TextInput;
|
||||||
|
use PHPNative\Ui\Window;
|
||||||
|
|
||||||
|
$app = new Application();
|
||||||
|
$window = new Window('Todo App', 600, 500);
|
||||||
|
|
||||||
|
// Main container
|
||||||
|
$mainContainer = new Container('flex flex-col p-4 bg-gray-50');
|
||||||
|
|
||||||
|
// Title
|
||||||
|
$title = new Label('My Todo List', 'text-2xl font-bold mb-4 text-gray-800');
|
||||||
|
$mainContainer->addComponent($title);
|
||||||
|
|
||||||
|
// Input section
|
||||||
|
$inputContainer = new Container('flex flex-row mb-4');
|
||||||
|
|
||||||
|
$input = new TextInput(
|
||||||
|
placeholder: 'What needs to be done?',
|
||||||
|
style: 'flex-1 p-2 border border-gray-300 rounded mr-2',
|
||||||
|
);
|
||||||
|
|
||||||
|
$addButton = new Button('Add', 'bg-blue-500 text-white p-2 rounded-lg hover:bg-blue-600');
|
||||||
|
|
||||||
|
$inputContainer->addComponent($input);
|
||||||
|
$inputContainer->addComponent($addButton);
|
||||||
|
$mainContainer->addComponent($inputContainer);
|
||||||
|
|
||||||
|
// Todo list container
|
||||||
|
$todoListContainer = new Container('flex flex-col');
|
||||||
|
$mainContainer->addComponent($todoListContainer);
|
||||||
|
|
||||||
|
// Stats
|
||||||
|
$statsLabel = new Label('0 items', 'mt-4 text-gray-600 text-sm h-10');
|
||||||
|
$mainContainer->addComponent($statsLabel);
|
||||||
|
|
||||||
|
// Todos array
|
||||||
|
$todos = [];
|
||||||
|
|
||||||
|
// Function to update stats
|
||||||
|
$updateStats = function () use (&$todos, $statsLabel) {
|
||||||
|
$total = count($todos);
|
||||||
|
$completed = count(array_filter($todos, fn($t) => $t['completed']));
|
||||||
|
$statsLabel->setText("{$total} items ({$completed} completed)");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to render todos - use a reference so it can be used in closures
|
||||||
|
$renderTodos = null;
|
||||||
|
$renderTodos = function () use (&$todos, $todoListContainer, $updateStats, &$renderTodos, $window) {
|
||||||
|
// Clear existing todos
|
||||||
|
$todoListContainer->clearChildren();
|
||||||
|
|
||||||
|
foreach ($todos as $index => $todo) {
|
||||||
|
$todoItem = new Container('flex flex-row items-center p-2 mb-2 bg-white border border-gray-200 rounded h-12');
|
||||||
|
|
||||||
|
// Checkbox
|
||||||
|
$checkbox = new Checkbox(
|
||||||
|
label: '',
|
||||||
|
checked: $todo['completed'],
|
||||||
|
style: 'mr-2 w-6 h-6',
|
||||||
|
);
|
||||||
|
|
||||||
|
$checkbox->setOnChange(function ($checked) use (&$todos, $index, &$renderTodos, $updateStats) {
|
||||||
|
$todos[$index]['completed'] = $checked;
|
||||||
|
$updateStats();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Text
|
||||||
|
$textStyle = $todo['completed'] ? 'flex-1 text-gray-400 line-through' : 'flex-1 text-gray-800';
|
||||||
|
$todoText = new Label($todo['text'], $textStyle);
|
||||||
|
|
||||||
|
// Delete button
|
||||||
|
$deleteButton = new Button('Delete', 'bg-red-500 text-white px-2 py-1 rounded text-sm hover:bg-red-600');
|
||||||
|
$deleteButton->setOnClick(function () use (&$todos, $index, &$renderTodos, $updateStats) {
|
||||||
|
array_splice($todos, $index, 1);
|
||||||
|
$renderTodos();
|
||||||
|
$updateStats();
|
||||||
|
});
|
||||||
|
|
||||||
|
$todoItem->addComponent($checkbox);
|
||||||
|
$todoItem->addComponent($todoText);
|
||||||
|
$todoItem->addComponent($deleteButton);
|
||||||
|
|
||||||
|
$todoListContainer->addComponent($todoItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
$updateStats();
|
||||||
|
|
||||||
|
// Trigger re-layout after adding new components
|
||||||
|
$window->setShouldBeReLayouted(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add button click handler
|
||||||
|
$addButton->setOnClick(function () use ($input, &$todos, &$renderTodos) {
|
||||||
|
$text = trim($input->getValue());
|
||||||
|
|
||||||
|
if (!empty($text)) {
|
||||||
|
$todos[] = [
|
||||||
|
'text' => $text,
|
||||||
|
'completed' => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
$input->setValue(''); // Clear input
|
||||||
|
$renderTodos();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle Enter key in input
|
||||||
|
$input->setOnChange(function ($value) {
|
||||||
|
// Could add live validation here
|
||||||
|
});
|
||||||
|
|
||||||
|
$window->setRoot($mainContainer);
|
||||||
|
$app->addWindow($window);
|
||||||
|
|
||||||
|
echo "Todo App started!\n";
|
||||||
|
echo "- Type in the input field and click 'Add' or press Enter\n";
|
||||||
|
echo "- Click checkboxes to mark todos as complete\n";
|
||||||
|
echo "- Click 'Delete' to remove a todo\n\n";
|
||||||
|
|
||||||
|
$app->run();
|
||||||
@ -14,7 +14,7 @@ library_names='sdl3.so sdl3.so sdl3.so'
|
|||||||
old_library=''
|
old_library=''
|
||||||
|
|
||||||
# Libraries that this one depends upon.
|
# Libraries that this one depends upon.
|
||||||
dependency_libs=' -L/usr/local/lib -lSDL3_gfx -lSDL3'
|
dependency_libs=' -L/usr/local/lib -lSDL3_gfx -lSDL3_image -lSDL3_ttf -lSDL3'
|
||||||
|
|
||||||
# Version information for sdl3.
|
# Version information for sdl3.
|
||||||
current=0
|
current=0
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
BIN
php-sdl3/.libs/sdl3_events.o
Normal file
BIN
php-sdl3/.libs/sdl3_events.o
Normal file
Binary file not shown.
BIN
php-sdl3/.libs/sdl3_image.o
Normal file
BIN
php-sdl3/.libs/sdl3_image.o
Normal file
Binary file not shown.
BIN
php-sdl3/.libs/sdl3_ttf.o
Normal file
BIN
php-sdl3/.libs/sdl3_ttf.o
Normal file
Binary file not shown.
@ -7,7 +7,7 @@ SED = /usr/bin/sed
|
|||||||
AWK = nawk
|
AWK = nawk
|
||||||
SHLIB_SUFFIX_NAME = so
|
SHLIB_SUFFIX_NAME = so
|
||||||
SHLIB_DL_SUFFIX_NAME = so
|
SHLIB_DL_SUFFIX_NAME = so
|
||||||
shared_objects_sdl3 = sdl3.lo helper.lo
|
shared_objects_sdl3 = sdl3.lo helper.lo sdl3_image.lo sdl3_ttf.lo sdl3_events.lo
|
||||||
PHP_PECL_EXTENSION = sdl3
|
PHP_PECL_EXTENSION = sdl3
|
||||||
PHP_MODULES = $(phplibdir)/sdl3.la
|
PHP_MODULES = $(phplibdir)/sdl3.la
|
||||||
PHP_ZEND_EX =
|
PHP_ZEND_EX =
|
||||||
@ -18,7 +18,7 @@ exec_prefix = $(prefix)
|
|||||||
libdir = ${exec_prefix}/lib
|
libdir = ${exec_prefix}/lib
|
||||||
phpincludedir = /usr/local/include/php
|
phpincludedir = /usr/local/include/php
|
||||||
CC = cc
|
CC = cc
|
||||||
CFLAGS = -g -O2 -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/local/include -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0
|
CFLAGS = -g -O2 -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/local/include -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/include/libpng16 -I/usr/include/x86_64-linux-gnu -I/usr/include/webp -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/sysprof-6 -pthread
|
||||||
CFLAGS_CLEAN = $(CFLAGS) -D_GNU_SOURCE
|
CFLAGS_CLEAN = $(CFLAGS) -D_GNU_SOURCE
|
||||||
CPP = cc -E
|
CPP = cc -E
|
||||||
CPPFLAGS = -DHAVE_CONFIG_H
|
CPPFLAGS = -DHAVE_CONFIG_H
|
||||||
@ -30,7 +30,7 @@ PHP_EXECUTABLE = /usr/local/bin/php
|
|||||||
EXTRA_LDFLAGS =
|
EXTRA_LDFLAGS =
|
||||||
EXTRA_LIBS =
|
EXTRA_LIBS =
|
||||||
INCLUDES = -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib
|
INCLUDES = -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib
|
||||||
LDFLAGS = -lSDL3 -L/usr/local/lib -lSDL3_gfx -lSDL3
|
LDFLAGS = -lSDL3 -L/usr/local/lib -lSDL3_gfx -lSDL3 -lSDL3_image -lSDL3 -lSDL3_ttf -lSDL3
|
||||||
LIBTOOL = $(SHELL) $(top_builddir)/libtool
|
LIBTOOL = $(SHELL) $(top_builddir)/libtool
|
||||||
SHELL = /bin/bash
|
SHELL = /bin/bash
|
||||||
INSTALL_HEADERS =
|
INSTALL_HEADERS =
|
||||||
@ -208,6 +208,15 @@ sdl3.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3.c
|
|||||||
-include helper.dep
|
-include helper.dep
|
||||||
helper.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/helper.c
|
helper.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/helper.c
|
||||||
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/helper.c -o helper.lo -MMD -MF helper.dep -MT helper.lo
|
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/helper.c -o helper.lo -MMD -MF helper.dep -MT helper.lo
|
||||||
|
-include sdl3_image.dep
|
||||||
|
sdl3_image.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_image.c
|
||||||
|
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_image.c -o sdl3_image.lo -MMD -MF sdl3_image.dep -MT sdl3_image.lo
|
||||||
|
-include sdl3_ttf.dep
|
||||||
|
sdl3_ttf.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_ttf.c
|
||||||
|
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_ttf.c -o sdl3_ttf.lo -MMD -MF sdl3_ttf.dep -MT sdl3_ttf.lo
|
||||||
|
-include sdl3_events.dep
|
||||||
|
sdl3_events.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_events.c
|
||||||
|
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_events.c -o sdl3_events.lo -MMD -MF sdl3_events.dep -MT sdl3_events.lo
|
||||||
$(phplibdir)/sdl3.la: ./sdl3.la
|
$(phplibdir)/sdl3.la: ./sdl3.la
|
||||||
$(LIBTOOL) --tag=CC --mode=install cp ./sdl3.la $(phplibdir)
|
$(LIBTOOL) --tag=CC --mode=install cp ./sdl3.la $(phplibdir)
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,15 @@ sdl3.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3.c
|
|||||||
-include helper.dep
|
-include helper.dep
|
||||||
helper.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/helper.c
|
helper.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/helper.c
|
||||||
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/helper.c -o helper.lo -MMD -MF helper.dep -MT helper.lo
|
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/helper.c -o helper.lo -MMD -MF helper.dep -MT helper.lo
|
||||||
|
-include sdl3_image.dep
|
||||||
|
sdl3_image.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_image.c
|
||||||
|
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_image.c -o sdl3_image.lo -MMD -MF sdl3_image.dep -MT sdl3_image.lo
|
||||||
|
-include sdl3_ttf.dep
|
||||||
|
sdl3_ttf.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_ttf.c
|
||||||
|
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_ttf.c -o sdl3_ttf.lo -MMD -MF sdl3_ttf.dep -MT sdl3_ttf.lo
|
||||||
|
-include sdl3_events.dep
|
||||||
|
sdl3_events.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_events.c
|
||||||
|
$(LIBTOOL) --tag=CC --mode=compile $(CC) -I. -I/home/thomas/projekte/phpnative/framework/php-sdl3 $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -DZEND_COMPILE_DL_EXT=1 -c /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_events.c -o sdl3_events.lo -MMD -MF sdl3_events.dep -MT sdl3_events.lo
|
||||||
$(phplibdir)/sdl3.la: ./sdl3.la
|
$(phplibdir)/sdl3.la: ./sdl3.la
|
||||||
$(LIBTOOL) --tag=CC --mode=install cp ./sdl3.la $(phplibdir)
|
$(LIBTOOL) --tag=CC --mode=install cp ./sdl3.la $(phplibdir)
|
||||||
|
|
||||||
|
|||||||
148
php-sdl3/button_example.php
Normal file
148
php-sdl3/button_example.php
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!extension_loaded('sdl3')) {
|
||||||
|
echo "Die Erweiterung 'sdl3' ist nicht geladen.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDL_INIT_VIDEO
|
||||||
|
const SDL_INIT_VIDEO = 0x00000020;
|
||||||
|
|
||||||
|
// Initialisierung
|
||||||
|
if (!sdl_init(SDL_INIT_VIDEO)) {
|
||||||
|
echo 'Fehler bei der Initialisierung von SDL: ' . sdl_get_error() . "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fenster erstellen
|
||||||
|
$window = sdl_create_window('SDL3 Button Beispiel', 640, 480);
|
||||||
|
if (!$window) {
|
||||||
|
echo 'Fehler beim Erstellen des Fensters: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderer erstellen
|
||||||
|
$renderer = sdl_create_renderer($window);
|
||||||
|
if (!$renderer) {
|
||||||
|
echo 'Fehler beim Erstellen des Renderers: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button-Eigenschaften
|
||||||
|
$button = [
|
||||||
|
'x' => 220,
|
||||||
|
'y' => 200,
|
||||||
|
'w' => 200,
|
||||||
|
'h' => 80,
|
||||||
|
'hovered' => false
|
||||||
|
];
|
||||||
|
|
||||||
|
// Hilfsfunktion: Prüft ob Punkt in Rechteck ist
|
||||||
|
function point_in_rect($x, $y, $rect) {
|
||||||
|
return $x >= $rect['x'] &&
|
||||||
|
$x <= $rect['x'] + $rect['w'] &&
|
||||||
|
$y >= $rect['y'] &&
|
||||||
|
$y <= $rect['y'] + $rect['h'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zeichnet den Button
|
||||||
|
function draw_button($renderer, $button) {
|
||||||
|
// Button-Hintergrund (grün wenn hovered, blau sonst)
|
||||||
|
if ($button['hovered']) {
|
||||||
|
sdl_set_render_draw_color($renderer, 50, 150, 50, 255);
|
||||||
|
} else {
|
||||||
|
sdl_set_render_draw_color($renderer, 70, 130, 180, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abgerundeter Button
|
||||||
|
sdl_rounded_box($renderer,
|
||||||
|
$button['x'], $button['y'],
|
||||||
|
$button['x'] + $button['w'], $button['y'] + $button['h'],
|
||||||
|
15,
|
||||||
|
$button['hovered'] ? 50 : 70,
|
||||||
|
$button['hovered'] ? 150 : 130,
|
||||||
|
$button['hovered'] ? 50 : 180,
|
||||||
|
255
|
||||||
|
);
|
||||||
|
|
||||||
|
// Button-Rahmen (dunkler)
|
||||||
|
sdl_set_render_draw_color($renderer, 40, 80, 120, 255);
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $button['x'],
|
||||||
|
'y' => $button['y'],
|
||||||
|
'w' => $button['w'],
|
||||||
|
'h' => 3
|
||||||
|
]);
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $button['x'],
|
||||||
|
'y' => $button['y'] + $button['h'] - 3,
|
||||||
|
'w' => $button['w'],
|
||||||
|
'h' => 3
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Button-Beispiel läuft!\n";
|
||||||
|
echo "Bewege die Maus über den blauen Button.\n";
|
||||||
|
echo "Klicke auf den Button um das Fenster zu schließen.\n";
|
||||||
|
|
||||||
|
// Hauptschleife
|
||||||
|
$running = true;
|
||||||
|
while ($running) {
|
||||||
|
// Events verarbeiten
|
||||||
|
while ($event = sdl_poll_event()) {
|
||||||
|
// Quit-Event
|
||||||
|
if ($event['type'] === SDL_EVENT_QUIT) {
|
||||||
|
$running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Window Close Button
|
||||||
|
if ($event['type'] === SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
|
||||||
|
$running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maus-Bewegung
|
||||||
|
if ($event['type'] === SDL_EVENT_MOUSE_MOTION) {
|
||||||
|
$button['hovered'] = point_in_rect($event['x'], $event['y'], $button);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maus-Klick
|
||||||
|
if ($event['type'] === SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
||||||
|
if ($event['button'] === SDL_BUTTON_LEFT) {
|
||||||
|
// Prüfe ob auf Button geklickt wurde
|
||||||
|
if (point_in_rect($event['x'], $event['y'], $button)) {
|
||||||
|
echo "Button wurde geklickt! Fenster wird geschlossen...\n";
|
||||||
|
$running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hintergrund zeichnen (hellgrau)
|
||||||
|
sdl_set_render_draw_color($renderer, 220, 220, 220, 255);
|
||||||
|
sdl_render_clear($renderer);
|
||||||
|
|
||||||
|
// Button zeichnen
|
||||||
|
draw_button($renderer, $button);
|
||||||
|
|
||||||
|
// Text-Bereich für "X Schließen" simulieren (schwarzes Rechteck in der Mitte)
|
||||||
|
$text_x = $button['x'] + ($button['w'] - 100) / 2;
|
||||||
|
$text_y = $button['y'] + ($button['h'] - 20) / 2;
|
||||||
|
sdl_set_render_draw_color($renderer, 255, 255, 255, 255);
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $text_x,
|
||||||
|
'y' => $text_y,
|
||||||
|
'w' => 100,
|
||||||
|
'h' => 20
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Anzeigen
|
||||||
|
sdl_render_present($renderer);
|
||||||
|
|
||||||
|
// Kurze Pause um CPU zu schonen
|
||||||
|
sdl_delay(16); // ~60 FPS
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Fenster geschlossen.\n";
|
||||||
|
sdl_quit();
|
||||||
166
php-sdl3/button_with_text.php
Normal file
166
php-sdl3/button_with_text.php
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!extension_loaded('sdl3')) {
|
||||||
|
echo "Die Erweiterung 'sdl3' ist nicht geladen.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDL_INIT_VIDEO
|
||||||
|
const SDL_INIT_VIDEO = 0x00000020;
|
||||||
|
|
||||||
|
// Initialisierung
|
||||||
|
if (!sdl_init(SDL_INIT_VIDEO)) {
|
||||||
|
echo 'Fehler bei der Initialisierung von SDL: ' . sdl_get_error() . "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TTF initialisieren
|
||||||
|
if (!ttf_init()) {
|
||||||
|
echo 'Fehler bei der Initialisierung von TTF: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fenster erstellen
|
||||||
|
$window = sdl_create_window('SDL3 Button mit Text', 640, 480);
|
||||||
|
if (!$window) {
|
||||||
|
echo 'Fehler beim Erstellen des Fensters: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderer erstellen
|
||||||
|
$renderer = sdl_create_renderer($window);
|
||||||
|
if (!$renderer) {
|
||||||
|
echo 'Fehler beim Erstellen des Renderers: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Font laden
|
||||||
|
$font = ttf_open_font('/usr/share/fonts/truetype/ubuntu/Ubuntu[wdth,wght].ttf', 24);
|
||||||
|
if (!$font) {
|
||||||
|
echo 'Fehler beim Laden der Schriftart: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text-Surface erstellen
|
||||||
|
$text_surface = ttf_render_text_solid($font, 'Schließen', 255, 255, 255);
|
||||||
|
if (!$text_surface) {
|
||||||
|
echo 'Fehler beim Rendern des Textes: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text-Texture erstellen
|
||||||
|
$text_texture = sdl_create_texture_from_surface($renderer, $text_surface);
|
||||||
|
if (!$text_texture) {
|
||||||
|
echo 'Fehler beim Erstellen der Text-Texture: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Textgröße ermitteln
|
||||||
|
$text_size = ttf_size_text($font, 'Schließen');
|
||||||
|
|
||||||
|
// Button-Eigenschaften
|
||||||
|
$button = [
|
||||||
|
'x' => 220,
|
||||||
|
'y' => 200,
|
||||||
|
'w' => 200,
|
||||||
|
'h' => 80,
|
||||||
|
'hovered' => false
|
||||||
|
];
|
||||||
|
|
||||||
|
// Hilfsfunktion: Prüft ob Punkt in Rechteck ist
|
||||||
|
function point_in_rect($x, $y, $rect) {
|
||||||
|
return $x >= $rect['x'] &&
|
||||||
|
$x <= $rect['x'] + $rect['w'] &&
|
||||||
|
$y >= $rect['y'] &&
|
||||||
|
$y <= $rect['y'] + $rect['h'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zeichnet den Button
|
||||||
|
function draw_button($renderer, $button, $text_texture, $text_size) {
|
||||||
|
// Button-Hintergrund (grün wenn hovered, blau sonst)
|
||||||
|
if ($button['hovered']) {
|
||||||
|
sdl_rounded_box($renderer,
|
||||||
|
$button['x'], $button['y'],
|
||||||
|
$button['x'] + $button['w'], $button['y'] + $button['h'],
|
||||||
|
15,
|
||||||
|
60, 180, 60, 255
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sdl_rounded_box($renderer,
|
||||||
|
$button['x'], $button['y'],
|
||||||
|
$button['x'] + $button['w'], $button['y'] + $button['h'],
|
||||||
|
15,
|
||||||
|
70, 130, 180, 255
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text zentriert auf Button rendern
|
||||||
|
$text_x = $button['x'] + ($button['w'] - $text_size['w']) / 2;
|
||||||
|
$text_y = $button['y'] + ($button['h'] - $text_size['h']) / 2;
|
||||||
|
|
||||||
|
sdl_render_texture($renderer, $text_texture, [
|
||||||
|
'x' => (int)$text_x,
|
||||||
|
'y' => (int)$text_y,
|
||||||
|
'w' => $text_size['w'],
|
||||||
|
'h' => $text_size['h']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Button-Beispiel mit Text läuft!\n";
|
||||||
|
echo "Bewege die Maus über den Button.\n";
|
||||||
|
echo "Klicke auf den 'Schließen'-Button um das Fenster zu schließen.\n";
|
||||||
|
|
||||||
|
// Hauptschleife
|
||||||
|
$running = true;
|
||||||
|
while ($running) {
|
||||||
|
// Events verarbeiten
|
||||||
|
while ($event = sdl_poll_event()) {
|
||||||
|
// Quit-Event
|
||||||
|
if ($event['type'] === SDL_EVENT_QUIT) {
|
||||||
|
$running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Window Close Button
|
||||||
|
if ($event['type'] === SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
|
||||||
|
$running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maus-Bewegung
|
||||||
|
if ($event['type'] === SDL_EVENT_MOUSE_MOTION) {
|
||||||
|
$button['hovered'] = point_in_rect($event['x'], $event['y'], $button);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maus-Klick
|
||||||
|
if ($event['type'] === SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
||||||
|
if ($event['button'] === SDL_BUTTON_LEFT) {
|
||||||
|
// Prüfe ob auf Button geklickt wurde
|
||||||
|
if (point_in_rect($event['x'], $event['y'], $button)) {
|
||||||
|
echo "Button wurde geklickt! Fenster wird geschlossen...\n";
|
||||||
|
$running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hintergrund zeichnen (dunkelgrau)
|
||||||
|
sdl_set_render_draw_color($renderer, 45, 45, 48, 255);
|
||||||
|
sdl_render_clear($renderer);
|
||||||
|
|
||||||
|
// Button zeichnen
|
||||||
|
draw_button($renderer, $button, $text_texture, $text_size);
|
||||||
|
|
||||||
|
// Anzeigen
|
||||||
|
sdl_render_present($renderer);
|
||||||
|
|
||||||
|
// Kurze Pause um CPU zu schonen
|
||||||
|
sdl_delay(16); // ~60 FPS
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Fenster geschlossen.\n";
|
||||||
|
sdl_quit();
|
||||||
@ -6,6 +6,14 @@ PHP_ARG_WITH(sdl3_gfx, [for sdl3_gfx support], [
|
|||||||
AS_HELP_STRING([--with-sdl3-gfx[=DIR]], [Enable sdl3_gfx support. DIR is the prefix for SDL3_gfx installation.])
|
AS_HELP_STRING([--with-sdl3-gfx[=DIR]], [Enable sdl3_gfx support. DIR is the prefix for SDL3_gfx installation.])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
PHP_ARG_WITH(sdl3_image, [for sdl3_image support], [
|
||||||
|
AS_HELP_STRING([--with-sdl3-image[=DIR]], [Enable sdl3_image support. DIR is the prefix for SDL3_image installation.])
|
||||||
|
])
|
||||||
|
|
||||||
|
PHP_ARG_WITH(sdl3_ttf, [for sdl3_ttf support], [
|
||||||
|
AS_HELP_STRING([--with-sdl3-ttf[=DIR]], [Enable sdl3_ttf support. DIR is the prefix for SDL3_ttf installation.])
|
||||||
|
])
|
||||||
|
|
||||||
if test "$PHP_SDL3" != "no"; then
|
if test "$PHP_SDL3" != "no"; then
|
||||||
if test -d "$PHP_SDL3"; then
|
if test -d "$PHP_SDL3"; then
|
||||||
PKG_CONFIG_PATH="$PHP_SDL3/lib/pkgconfig:$PHP_SDL3/share/pkgconfig:$PKG_CONFIG_PATH"
|
PKG_CONFIG_PATH="$PHP_SDL3/lib/pkgconfig:$PHP_SDL3/share/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
@ -31,7 +39,33 @@ if test "$PHP_SDL3" != "no"; then
|
|||||||
])
|
])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SDL_SOURCE_FILES="sdl3.c helper.c"
|
if test "$PHP_SDL3_IMAGE" != "no"; then
|
||||||
|
if test -d "$PHP_SDL3_IMAGE"; then
|
||||||
|
PKG_CONFIG_PATH="$PHP_SDL3_IMAGE/lib/pkgconfig:$PHP_SDL3_IMAGE/share/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES([SDL3_IMAGE], [sdl3-image >= 3.0.0], [
|
||||||
|
CFLAGS="$CFLAGS $SDL3_IMAGE_CFLAGS"
|
||||||
|
LDFLAGS="$LDFLAGS $SDL3_IMAGE_LIBS"
|
||||||
|
],[
|
||||||
|
AC_MSG_ERROR([SDL3_image not found. Please check your installation or use --with-sdl3-image=/path/to/sdl3_image])
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$PHP_SDL3_TTF" != "no"; then
|
||||||
|
if test -d "$PHP_SDL3_TTF"; then
|
||||||
|
PKG_CONFIG_PATH="$PHP_SDL3_TTF/lib/pkgconfig:$PHP_SDL3_TTF/share/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES([SDL3_TTF], [sdl3-ttf >= 3.0.0], [
|
||||||
|
CFLAGS="$CFLAGS $SDL3_TTF_CFLAGS"
|
||||||
|
LDFLAGS="$LDFLAGS $SDL3_TTF_LIBS"
|
||||||
|
],[
|
||||||
|
AC_MSG_ERROR([SDL3_ttf not found. Please check your installation or use --with-sdl3-ttf=/path/to/sdl3_ttf])
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
|
||||||
|
SDL_SOURCE_FILES="sdl3.c helper.c sdl3_image.c sdl3_ttf.c sdl3_events.c"
|
||||||
|
|
||||||
PHP_NEW_EXTENSION(sdl3, $SDL_SOURCE_FILES, $ext_shared)
|
PHP_NEW_EXTENSION(sdl3, $SDL_SOURCE_FILES, $ext_shared)
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -3,5 +3,8 @@
|
|||||||
# Created by configure
|
# Created by configure
|
||||||
|
|
||||||
'./configure' \
|
'./configure' \
|
||||||
|
'--with-sdl3=/usr/local' \
|
||||||
'--with-sdl3-gfx=/usr/local' \
|
'--with-sdl3-gfx=/usr/local' \
|
||||||
|
'--with-sdl3-image=/usr/local' \
|
||||||
|
'--with-sdl3-ttf=/usr/local' \
|
||||||
"$@"
|
"$@"
|
||||||
|
|||||||
@ -413,7 +413,7 @@ $config_headers
|
|||||||
|
|
||||||
Report bugs to the package provider."
|
Report bugs to the package provider."
|
||||||
|
|
||||||
ac_cs_config='--with-sdl3-gfx=/usr/local'
|
ac_cs_config='--with-sdl3=/usr/local --with-sdl3-gfx=/usr/local --with-sdl3-image=/usr/local --with-sdl3-ttf=/usr/local'
|
||||||
ac_cs_version="\
|
ac_cs_version="\
|
||||||
config.status
|
config.status
|
||||||
configured by ./configure, generated by GNU Autoconf 2.72,
|
configured by ./configure, generated by GNU Autoconf 2.72,
|
||||||
@ -494,7 +494,7 @@ if $ac_cs_silent; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if $ac_cs_recheck; then
|
if $ac_cs_recheck; then
|
||||||
set X /bin/bash './configure' '--with-sdl3-gfx=/usr/local' $ac_configure_extra_args --no-create --no-recursion
|
set X /bin/bash './configure' '--with-sdl3=/usr/local' '--with-sdl3-gfx=/usr/local' '--with-sdl3-image=/usr/local' '--with-sdl3-ttf=/usr/local' $ac_configure_extra_args --no-create --no-recursion
|
||||||
shift
|
shift
|
||||||
\printf "%s\n" "running CONFIG_SHELL=/bin/bash $*" >&6
|
\printf "%s\n" "running CONFIG_SHELL=/bin/bash $*" >&6
|
||||||
CONFIG_SHELL='/bin/bash'
|
CONFIG_SHELL='/bin/bash'
|
||||||
|
|||||||
338
php-sdl3/configure
vendored
338
php-sdl3/configure
vendored
@ -802,6 +802,10 @@ RANLIB
|
|||||||
AR
|
AR
|
||||||
ECHO
|
ECHO
|
||||||
LN_S
|
LN_S
|
||||||
|
SDL3_TTF_LIBS
|
||||||
|
SDL3_TTF_CFLAGS
|
||||||
|
SDL3_IMAGE_LIBS
|
||||||
|
SDL3_IMAGE_CFLAGS
|
||||||
SDL3_GFX_LIBS
|
SDL3_GFX_LIBS
|
||||||
SDL3_GFX_CFLAGS
|
SDL3_GFX_CFLAGS
|
||||||
SDL3_LIBS
|
SDL3_LIBS
|
||||||
@ -884,6 +888,8 @@ with_php_config
|
|||||||
enable_
|
enable_
|
||||||
with_sdl3
|
with_sdl3
|
||||||
with_sdl3_gfx
|
with_sdl3_gfx
|
||||||
|
with_sdl3_image
|
||||||
|
with_sdl3_ttf
|
||||||
enable_shared
|
enable_shared
|
||||||
enable_static
|
enable_static
|
||||||
enable_fast_install
|
enable_fast_install
|
||||||
@ -907,7 +913,11 @@ CPP
|
|||||||
SDL3_CFLAGS
|
SDL3_CFLAGS
|
||||||
SDL3_LIBS
|
SDL3_LIBS
|
||||||
SDL3_GFX_CFLAGS
|
SDL3_GFX_CFLAGS
|
||||||
SDL3_GFX_LIBS'
|
SDL3_GFX_LIBS
|
||||||
|
SDL3_IMAGE_CFLAGS
|
||||||
|
SDL3_IMAGE_LIBS
|
||||||
|
SDL3_TTF_CFLAGS
|
||||||
|
SDL3_TTF_LIBS'
|
||||||
|
|
||||||
|
|
||||||
# Initialize some variables set by options.
|
# Initialize some variables set by options.
|
||||||
@ -1544,6 +1554,14 @@ Extension:
|
|||||||
SDL3_gfx installation.
|
SDL3_gfx installation.
|
||||||
|
|
||||||
|
|
||||||
|
--with-sdl3-image=DIR Enable sdl3_image support. DIR is the prefix for
|
||||||
|
SDL3_image installation.
|
||||||
|
|
||||||
|
|
||||||
|
--with-sdl3-ttf=DIR Enable sdl3_ttf support. DIR is the prefix for
|
||||||
|
SDL3_ttf installation.
|
||||||
|
|
||||||
|
|
||||||
Libtool:
|
Libtool:
|
||||||
--enable-shared=PKGS Build shared libraries default=yes
|
--enable-shared=PKGS Build shared libraries default=yes
|
||||||
--enable-static=PKGS Build static libraries default=yes
|
--enable-static=PKGS Build static libraries default=yes
|
||||||
@ -1575,6 +1593,14 @@ Some influential environment variables:
|
|||||||
C compiler flags for SDL3_GFX, overriding pkg-config
|
C compiler flags for SDL3_GFX, overriding pkg-config
|
||||||
SDL3_GFX_LIBS
|
SDL3_GFX_LIBS
|
||||||
linker flags for SDL3_GFX, overriding pkg-config
|
linker flags for SDL3_GFX, overriding pkg-config
|
||||||
|
SDL3_IMAGE_CFLAGS
|
||||||
|
C compiler flags for SDL3_IMAGE, overriding pkg-config
|
||||||
|
SDL3_IMAGE_LIBS
|
||||||
|
linker flags for SDL3_IMAGE, overriding pkg-config
|
||||||
|
SDL3_TTF_CFLAGS
|
||||||
|
C compiler flags for SDL3_TTF, overriding pkg-config
|
||||||
|
SDL3_TTF_LIBS
|
||||||
|
linker flags for SDL3_TTF, overriding pkg-config
|
||||||
|
|
||||||
Use these variables to override the choices made by 'configure' or to help
|
Use these variables to override the choices made by 'configure' or to help
|
||||||
it to find libraries and programs with nonstandard names/locations.
|
it to find libraries and programs with nonstandard names/locations.
|
||||||
@ -4801,6 +4827,108 @@ printf "%s\n" "$ext_output" >&6; }
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
php_with_sdl3_image=no
|
||||||
|
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sdl3_image support" >&5
|
||||||
|
printf %s "checking for sdl3_image support... " >&6; }
|
||||||
|
|
||||||
|
# Check whether --with-sdl3_image was given.
|
||||||
|
if test ${with_sdl3_image+y}
|
||||||
|
then :
|
||||||
|
withval=$with_sdl3_image; PHP_SDL3_IMAGE=$withval
|
||||||
|
else case e in #(
|
||||||
|
e)
|
||||||
|
PHP_SDL3_IMAGE=no
|
||||||
|
test "$PHP_ENABLE_ALL" && PHP_SDL3_IMAGE=$PHP_ENABLE_ALL
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ext_output="yes, shared"
|
||||||
|
ext_shared=yes
|
||||||
|
case $PHP_SDL3_IMAGE in
|
||||||
|
shared,*)
|
||||||
|
PHP_SDL3_IMAGE=$(echo "$PHP_SDL3_IMAGE"|$SED 's/^shared,//')
|
||||||
|
;;
|
||||||
|
shared)
|
||||||
|
PHP_SDL3_IMAGE=yes
|
||||||
|
;;
|
||||||
|
no)
|
||||||
|
ext_output=no
|
||||||
|
ext_shared=no
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ext_output=yes
|
||||||
|
ext_shared=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
ext_output="yes, shared"
|
||||||
|
ext_shared=yes
|
||||||
|
test "$PHP_SDL3_IMAGE" = "no" && PHP_SDL3_IMAGE=yes
|
||||||
|
|
||||||
|
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ext_output" >&5
|
||||||
|
printf "%s\n" "$ext_output" >&6; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
php_with_sdl3_ttf=no
|
||||||
|
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sdl3_ttf support" >&5
|
||||||
|
printf %s "checking for sdl3_ttf support... " >&6; }
|
||||||
|
|
||||||
|
# Check whether --with-sdl3_ttf was given.
|
||||||
|
if test ${with_sdl3_ttf+y}
|
||||||
|
then :
|
||||||
|
withval=$with_sdl3_ttf; PHP_SDL3_TTF=$withval
|
||||||
|
else case e in #(
|
||||||
|
e)
|
||||||
|
PHP_SDL3_TTF=no
|
||||||
|
test "$PHP_ENABLE_ALL" && PHP_SDL3_TTF=$PHP_ENABLE_ALL
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ext_output="yes, shared"
|
||||||
|
ext_shared=yes
|
||||||
|
case $PHP_SDL3_TTF in
|
||||||
|
shared,*)
|
||||||
|
PHP_SDL3_TTF=$(echo "$PHP_SDL3_TTF"|$SED 's/^shared,//')
|
||||||
|
;;
|
||||||
|
shared)
|
||||||
|
PHP_SDL3_TTF=yes
|
||||||
|
;;
|
||||||
|
no)
|
||||||
|
ext_output=no
|
||||||
|
ext_shared=no
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ext_output=yes
|
||||||
|
ext_shared=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
ext_output="yes, shared"
|
||||||
|
ext_shared=yes
|
||||||
|
test "$PHP_SDL3_TTF" = "no" && PHP_SDL3_TTF=yes
|
||||||
|
|
||||||
|
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ext_output" >&5
|
||||||
|
printf "%s\n" "$ext_output" >&6; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if test "$PHP_SDL3" != "no"; then
|
if test "$PHP_SDL3" != "no"; then
|
||||||
if test -d "$PHP_SDL3"; then
|
if test -d "$PHP_SDL3"; then
|
||||||
PKG_CONFIG_PATH="$PHP_SDL3/lib/pkgconfig:$PHP_SDL3/share/pkgconfig:$PKG_CONFIG_PATH"
|
PKG_CONFIG_PATH="$PHP_SDL3/lib/pkgconfig:$PHP_SDL3/share/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
@ -4970,7 +5098,177 @@ printf "%s\n" "yes" >&6; }
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SDL_SOURCE_FILES="sdl3.c helper.c"
|
if test "$PHP_SDL3_IMAGE" != "no"; then
|
||||||
|
if test -d "$PHP_SDL3_IMAGE"; then
|
||||||
|
PKG_CONFIG_PATH="$PHP_SDL3_IMAGE/lib/pkgconfig:$PHP_SDL3_IMAGE/share/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
pkg_failed=no
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sdl3-image >= 3.0.0" >&5
|
||||||
|
printf %s "checking for sdl3-image >= 3.0.0... " >&6; }
|
||||||
|
|
||||||
|
if test -n "$SDL3_IMAGE_CFLAGS"; then
|
||||||
|
pkg_cv_SDL3_IMAGE_CFLAGS="$SDL3_IMAGE_CFLAGS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl3-image >= 3.0.0\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "sdl3-image >= 3.0.0") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_SDL3_IMAGE_CFLAGS=`$PKG_CONFIG --cflags "sdl3-image >= 3.0.0" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
if test -n "$SDL3_IMAGE_LIBS"; then
|
||||||
|
pkg_cv_SDL3_IMAGE_LIBS="$SDL3_IMAGE_LIBS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl3-image >= 3.0.0\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "sdl3-image >= 3.0.0") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_SDL3_IMAGE_LIBS=`$PKG_CONFIG --libs "sdl3-image >= 3.0.0" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if test $pkg_failed = yes; then
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
|
_pkg_short_errors_supported=yes
|
||||||
|
else
|
||||||
|
_pkg_short_errors_supported=no
|
||||||
|
fi
|
||||||
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
|
SDL3_IMAGE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl3-image >= 3.0.0" 2>&1`
|
||||||
|
else
|
||||||
|
SDL3_IMAGE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl3-image >= 3.0.0" 2>&1`
|
||||||
|
fi
|
||||||
|
# Put the nasty error message in config.log where it belongs
|
||||||
|
echo "$SDL3_IMAGE_PKG_ERRORS" >&5
|
||||||
|
|
||||||
|
|
||||||
|
as_fn_error $? "SDL3_image not found. Please check your installation or use --with-sdl3-image=/path/to/sdl3_image" "$LINENO" 5
|
||||||
|
|
||||||
|
elif test $pkg_failed = untried; then
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
|
as_fn_error $? "SDL3_image not found. Please check your installation or use --with-sdl3-image=/path/to/sdl3_image" "$LINENO" 5
|
||||||
|
|
||||||
|
else
|
||||||
|
SDL3_IMAGE_CFLAGS=$pkg_cv_SDL3_IMAGE_CFLAGS
|
||||||
|
SDL3_IMAGE_LIBS=$pkg_cv_SDL3_IMAGE_LIBS
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
printf "%s\n" "yes" >&6; }
|
||||||
|
|
||||||
|
CFLAGS="$CFLAGS $SDL3_IMAGE_CFLAGS"
|
||||||
|
LDFLAGS="$LDFLAGS $SDL3_IMAGE_LIBS"
|
||||||
|
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$PHP_SDL3_TTF" != "no"; then
|
||||||
|
if test -d "$PHP_SDL3_TTF"; then
|
||||||
|
PKG_CONFIG_PATH="$PHP_SDL3_TTF/lib/pkgconfig:$PHP_SDL3_TTF/share/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
pkg_failed=no
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sdl3-ttf >= 3.0.0" >&5
|
||||||
|
printf %s "checking for sdl3-ttf >= 3.0.0... " >&6; }
|
||||||
|
|
||||||
|
if test -n "$SDL3_TTF_CFLAGS"; then
|
||||||
|
pkg_cv_SDL3_TTF_CFLAGS="$SDL3_TTF_CFLAGS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl3-ttf >= 3.0.0\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "sdl3-ttf >= 3.0.0") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_SDL3_TTF_CFLAGS=`$PKG_CONFIG --cflags "sdl3-ttf >= 3.0.0" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
if test -n "$SDL3_TTF_LIBS"; then
|
||||||
|
pkg_cv_SDL3_TTF_LIBS="$SDL3_TTF_LIBS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl3-ttf >= 3.0.0\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "sdl3-ttf >= 3.0.0") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_SDL3_TTF_LIBS=`$PKG_CONFIG --libs "sdl3-ttf >= 3.0.0" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if test $pkg_failed = yes; then
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
|
_pkg_short_errors_supported=yes
|
||||||
|
else
|
||||||
|
_pkg_short_errors_supported=no
|
||||||
|
fi
|
||||||
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
|
SDL3_TTF_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl3-ttf >= 3.0.0" 2>&1`
|
||||||
|
else
|
||||||
|
SDL3_TTF_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl3-ttf >= 3.0.0" 2>&1`
|
||||||
|
fi
|
||||||
|
# Put the nasty error message in config.log where it belongs
|
||||||
|
echo "$SDL3_TTF_PKG_ERRORS" >&5
|
||||||
|
|
||||||
|
|
||||||
|
as_fn_error $? "SDL3_ttf not found. Please check your installation or use --with-sdl3-ttf=/path/to/sdl3_ttf" "$LINENO" 5
|
||||||
|
|
||||||
|
elif test $pkg_failed = untried; then
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
printf "%s\n" "no" >&6; }
|
||||||
|
|
||||||
|
as_fn_error $? "SDL3_ttf not found. Please check your installation or use --with-sdl3-ttf=/path/to/sdl3_ttf" "$LINENO" 5
|
||||||
|
|
||||||
|
else
|
||||||
|
SDL3_TTF_CFLAGS=$pkg_cv_SDL3_TTF_CFLAGS
|
||||||
|
SDL3_TTF_LIBS=$pkg_cv_SDL3_TTF_LIBS
|
||||||
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
printf "%s\n" "yes" >&6; }
|
||||||
|
|
||||||
|
CFLAGS="$CFLAGS $SDL3_TTF_CFLAGS"
|
||||||
|
LDFLAGS="$LDFLAGS $SDL3_TTF_LIBS"
|
||||||
|
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
SDL_SOURCE_FILES="sdl3.c helper.c sdl3_image.c sdl3_ttf.c sdl3_events.c"
|
||||||
|
|
||||||
|
|
||||||
ext_builddir=.
|
ext_builddir=.
|
||||||
@ -5825,7 +6123,7 @@ ia64-*-hpux*)
|
|||||||
;;
|
;;
|
||||||
*-*-irix6*)
|
*-*-irix6*)
|
||||||
# Find out which ABI we are using.
|
# Find out which ABI we are using.
|
||||||
echo '#line 5828 "configure"' > conftest.$ac_ext
|
echo '#line 6126 "configure"' > conftest.$ac_ext
|
||||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||||
(eval $ac_compile) 2>&5
|
(eval $ac_compile) 2>&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
@ -7204,7 +7502,7 @@ else case e in #(
|
|||||||
LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
|
LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
|
||||||
|
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 7207 "configure"
|
#line 7505 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
int main(void) {
|
int main(void) {
|
||||||
; return 0; }
|
; return 0; }
|
||||||
@ -7366,11 +7664,11 @@ else case e in #(
|
|||||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||||
-e 's:$: $lt_compiler_flag:'`
|
-e 's:$: $lt_compiler_flag:'`
|
||||||
(eval echo "\"configure:7369: $lt_compile\"" >&5)
|
(eval echo "\"configure:7667: $lt_compile\"" >&5)
|
||||||
(eval "$lt_compile" 2>conftest.err)
|
(eval "$lt_compile" 2>conftest.err)
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
cat conftest.err >&5
|
cat conftest.err >&5
|
||||||
echo "configure:7373: \$? = $ac_status" >&5
|
echo "configure:7671: \$? = $ac_status" >&5
|
||||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||||
# The compiler can only warn and ignore the option if not recognized
|
# The compiler can only warn and ignore the option if not recognized
|
||||||
# So say no if there are warnings other than the usual output.
|
# So say no if there are warnings other than the usual output.
|
||||||
@ -7666,11 +7964,11 @@ else case e in #(
|
|||||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||||
-e 's:$: $lt_compiler_flag:'`
|
-e 's:$: $lt_compiler_flag:'`
|
||||||
(eval echo "\"configure:7669: $lt_compile\"" >&5)
|
(eval echo "\"configure:7967: $lt_compile\"" >&5)
|
||||||
(eval "$lt_compile" 2>conftest.err)
|
(eval "$lt_compile" 2>conftest.err)
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
cat conftest.err >&5
|
cat conftest.err >&5
|
||||||
echo "configure:7673: \$? = $ac_status" >&5
|
echo "configure:7971: \$? = $ac_status" >&5
|
||||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||||
# The compiler can only warn and ignore the option if not recognized
|
# The compiler can only warn and ignore the option if not recognized
|
||||||
# So say no if there are warnings other than the usual output.
|
# So say no if there are warnings other than the usual output.
|
||||||
@ -7774,11 +8072,11 @@ else case e in #(
|
|||||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||||
-e 's:$: $lt_compiler_flag:'`
|
-e 's:$: $lt_compiler_flag:'`
|
||||||
(eval echo "\"configure:7777: $lt_compile\"" >&5)
|
(eval echo "\"configure:8075: $lt_compile\"" >&5)
|
||||||
(eval "$lt_compile" 2>out/conftest.err)
|
(eval "$lt_compile" 2>out/conftest.err)
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
cat out/conftest.err >&5
|
cat out/conftest.err >&5
|
||||||
echo "configure:7781: \$? = $ac_status" >&5
|
echo "configure:8079: \$? = $ac_status" >&5
|
||||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||||
then
|
then
|
||||||
# The compiler can only warn and ignore the option if not recognized
|
# The compiler can only warn and ignore the option if not recognized
|
||||||
@ -8239,7 +8537,7 @@ _LT_EOF
|
|||||||
# Determine the default libpath from the value encoded in an empty executable.
|
# Determine the default libpath from the value encoded in an empty executable.
|
||||||
|
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 8242 "configure"
|
#line 8540 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
int main(void) {
|
int main(void) {
|
||||||
; return 0; }
|
; return 0; }
|
||||||
@ -8281,7 +8579,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
|
|||||||
# Determine the default libpath from the value encoded in an empty executable.
|
# Determine the default libpath from the value encoded in an empty executable.
|
||||||
|
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 8284 "configure"
|
#line 8582 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
int main(void) {
|
int main(void) {
|
||||||
; return 0; }
|
; return 0; }
|
||||||
@ -9862,7 +10160,7 @@ else
|
|||||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||||
lt_status=$lt_dlunknown
|
lt_status=$lt_dlunknown
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 9865 "configure"
|
#line 10163 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
#if HAVE_DLFCN_H
|
#if HAVE_DLFCN_H
|
||||||
@ -9961,7 +10259,7 @@ else
|
|||||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||||
lt_status=$lt_dlunknown
|
lt_status=$lt_dlunknown
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 9964 "configure"
|
#line 10262 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
#if HAVE_DLFCN_H
|
#if HAVE_DLFCN_H
|
||||||
@ -11030,7 +11328,7 @@ case $host_os in
|
|||||||
# Determine the default libpath from the value encoded in an empty executable.
|
# Determine the default libpath from the value encoded in an empty executable.
|
||||||
|
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 11033 "configure"
|
#line 11331 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
int main(void) {
|
int main(void) {
|
||||||
; return 0; }
|
; return 0; }
|
||||||
@ -11073,7 +11371,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
|
|||||||
# Determine the default libpath from the value encoded in an empty executable.
|
# Determine the default libpath from the value encoded in an empty executable.
|
||||||
|
|
||||||
cat > conftest.$ac_ext <<EOF
|
cat > conftest.$ac_ext <<EOF
|
||||||
#line 11076 "configure"
|
#line 11374 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
int main(void) {
|
int main(void) {
|
||||||
; return 0; }
|
; return 0; }
|
||||||
@ -12326,11 +12624,11 @@ else case e in #(
|
|||||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||||
-e 's:$: $lt_compiler_flag:'`
|
-e 's:$: $lt_compiler_flag:'`
|
||||||
(eval echo "\"configure:12329: $lt_compile\"" >&5)
|
(eval echo "\"configure:12627: $lt_compile\"" >&5)
|
||||||
(eval "$lt_compile" 2>conftest.err)
|
(eval "$lt_compile" 2>conftest.err)
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
cat conftest.err >&5
|
cat conftest.err >&5
|
||||||
echo "configure:12333: \$? = $ac_status" >&5
|
echo "configure:12631: \$? = $ac_status" >&5
|
||||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||||
# The compiler can only warn and ignore the option if not recognized
|
# The compiler can only warn and ignore the option if not recognized
|
||||||
# So say no if there are warnings other than the usual output.
|
# So say no if there are warnings other than the usual output.
|
||||||
@ -12434,11 +12732,11 @@ else case e in #(
|
|||||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||||
-e 's:$: $lt_compiler_flag:'`
|
-e 's:$: $lt_compiler_flag:'`
|
||||||
(eval echo "\"configure:12437: $lt_compile\"" >&5)
|
(eval echo "\"configure:12735: $lt_compile\"" >&5)
|
||||||
(eval "$lt_compile" 2>out/conftest.err)
|
(eval "$lt_compile" 2>out/conftest.err)
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
cat out/conftest.err >&5
|
cat out/conftest.err >&5
|
||||||
echo "configure:12441: \$? = $ac_status" >&5
|
echo "configure:12739: \$? = $ac_status" >&5
|
||||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||||
then
|
then
|
||||||
# The compiler can only warn and ignore the option if not recognized
|
# The compiler can only warn and ignore the option if not recognized
|
||||||
|
|||||||
@ -33,10 +33,10 @@ sdl_render_clear($renderer);
|
|||||||
|
|
||||||
// Ein grünes, abgerundetes Rechteck mit verschiedenen Radien zeichnen
|
// Ein grünes, abgerundetes Rechteck mit verschiedenen Radien zeichnen
|
||||||
// Radien: Oben-Links, Oben-Rechts, Unten-Rechts, Unten-Links
|
// Radien: Oben-Links, Oben-Rechts, Unten-Rechts, Unten-Links
|
||||||
$rad_tl = 20;
|
$rad_tl = 40;
|
||||||
$rad_tr = 20;
|
$rad_tr = 10;
|
||||||
$rad_br = 20;
|
$rad_br = 40;
|
||||||
$rad_bl = 20;
|
$rad_bl = 10;
|
||||||
sdl_rounded_box_ex($renderer, 100, 100, 200, 200, $rad_tl, $rad_tr, $rad_br, $rad_bl, 30, 200, 70, 255);
|
sdl_rounded_box_ex($renderer, 100, 100, 200, 200, $rad_tl, $rad_tr, $rad_br, $rad_bl, 30, 200, 70, 255);
|
||||||
|
|
||||||
// Alles auf dem Bildschirm anzeigen
|
// Alles auf dem Bildschirm anzeigen
|
||||||
|
|||||||
@ -2,35 +2,34 @@
|
|||||||
#define PHP_SDL3_HELPER
|
#define PHP_SDL3_HELPER
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3_gfx/SDL3_gfxPrimitives.h>
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
static void draw_hline(SDL_Renderer *renderer, int x1, int x2, int y) {
|
|
||||||
if (x2 < x1) return;
|
|
||||||
SDL_RenderLine(renderer, x1, y, x2, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zeichnet einen gefüllten Viertel-Kreis (filled quarter circle).
|
// Zeichnet einen gefüllten Viertel-Kreis mit Anti-Aliasing (filled quarter circle).
|
||||||
// quadrant: 0 = top-left, 1 = top-right, 2 = bottom-right, 3 = bottom-left
|
// quadrant: 0 = top-left, 1 = top-right, 2 = bottom-right, 3 = bottom-left
|
||||||
static void filled_quarter_circle(SDL_Renderer *renderer, int cx, int cy, int r, int quadrant) {
|
static void filled_quarter_circle(SDL_Renderer *renderer, int cx, int cy, int r, int quadrant) {
|
||||||
if (r <= 0) return;
|
if (r <= 0) return;
|
||||||
int r2 = r * r;
|
|
||||||
for (int dy = 0; dy <= r; ++dy) {
|
// Get current draw color
|
||||||
// dy ist vertikale Distanz vom Kreiszentrum (0..r)
|
Uint8 r_col, g_col, b_col, a_col;
|
||||||
int dx = (int)floor(sqrt((double)r2 - (double)dy * dy));
|
SDL_GetRenderDrawColor(renderer, &r_col, &g_col, &b_col, &a_col);
|
||||||
|
|
||||||
|
// Use SDL_gfx filledCircle with proper quadrant rendering
|
||||||
|
// We'll draw the arc using the primitives library
|
||||||
switch (quadrant) {
|
switch (quadrant) {
|
||||||
case 0: // top-left: y = cy - dy, x in [cx - dx, cx]
|
case 0: // top-left
|
||||||
draw_hline(renderer, cx - dx, cx, cy - dy);
|
filledPieRGBA(renderer, cx, cy, r, 180, 270, r_col, g_col, b_col, a_col);
|
||||||
break;
|
break;
|
||||||
case 1: // top-right: y = cy - dy, x in [cx, cx + dx]
|
case 1: // top-right
|
||||||
draw_hline(renderer, cx, cx + dx, cy - dy);
|
filledPieRGBA(renderer, cx, cy, r, 270, 360, r_col, g_col, b_col, a_col);
|
||||||
break;
|
break;
|
||||||
case 2: // bottom-right: y = cy + dy, x in [cx, cx + dx]
|
case 2: // bottom-right
|
||||||
draw_hline(renderer, cx, cx + dx, cy + dy);
|
filledPieRGBA(renderer, cx, cy, r, 0, 90, r_col, g_col, b_col, a_col);
|
||||||
break;
|
break;
|
||||||
case 3: // bottom-left: y = cy + dy, x in [cx - dx, cx]
|
case 3: // bottom-left
|
||||||
draw_hline(renderer, cx - dx, cx, cy + dy);
|
filledPieRGBA(renderer, cx, cy, r, 90, 180, r_col, g_col, b_col, a_col);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -85,7 +85,7 @@ AR_FLAGS="cru"
|
|||||||
LTCC="cc"
|
LTCC="cc"
|
||||||
|
|
||||||
# LTCC compiler flags.
|
# LTCC compiler flags.
|
||||||
LTCFLAGS="-g -O2 -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/local/include -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 "
|
LTCFLAGS="-g -O2 -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/local/include -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/include/libpng16 -I/usr/include/x86_64-linux-gnu -I/usr/include/webp -I/usr/include/pipewire-0.3 -I/usr/include/spa-0.2 -D_REENTRANT -I/usr/include/libdrm -I/usr/include/libdecor-0 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/sysprof-6 -pthread "
|
||||||
|
|
||||||
# A language-specific compiler.
|
# A language-specific compiler.
|
||||||
CC="cc"
|
CC="cc"
|
||||||
|
|||||||
@ -14,7 +14,7 @@ library_names='sdl3.so sdl3.so sdl3.so'
|
|||||||
old_library=''
|
old_library=''
|
||||||
|
|
||||||
# Libraries that this one depends upon.
|
# Libraries that this one depends upon.
|
||||||
dependency_libs=' -L/usr/local/lib -lSDL3_gfx -lSDL3'
|
dependency_libs=' -L/usr/local/lib -lSDL3_gfx -lSDL3_image -lSDL3_ttf -lSDL3'
|
||||||
|
|
||||||
# Version information for sdl3.
|
# Version information for sdl3.
|
||||||
current=0
|
current=0
|
||||||
|
|||||||
Binary file not shown.
243
php-sdl3/multi_window_example.php
Normal file
243
php-sdl3/multi_window_example.php
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!extension_loaded('sdl3')) {
|
||||||
|
echo "Die Erweiterung 'sdl3' ist nicht geladen.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDL_INIT_VIDEO
|
||||||
|
const SDL_INIT_VIDEO = 0x00000020;
|
||||||
|
|
||||||
|
// Initialisierung
|
||||||
|
if (!sdl_init(SDL_INIT_VIDEO)) {
|
||||||
|
echo 'Fehler bei der Initialisierung von SDL: ' . sdl_get_error() . "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TTF initialisieren
|
||||||
|
if (!ttf_init()) {
|
||||||
|
echo 'Fehler bei der Initialisierung von TTF: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Font laden
|
||||||
|
$font = ttf_open_font('/usr/share/fonts/truetype/ubuntu/Ubuntu[wdth,wght].ttf', 24);
|
||||||
|
if (!$font) {
|
||||||
|
echo 'Fehler beim Laden der Schriftart: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hauptfenster erstellen
|
||||||
|
$main_window = sdl_create_window('Hauptfenster', 640, 480);
|
||||||
|
if (!$main_window) {
|
||||||
|
echo 'Fehler beim Erstellen des Hauptfensters: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$main_renderer = sdl_create_renderer($main_window);
|
||||||
|
if (!$main_renderer) {
|
||||||
|
echo 'Fehler beim Erstellen des Hauptrenderers: ' . sdl_get_error() . "\n";
|
||||||
|
sdl_quit();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Window IDs speichern
|
||||||
|
$main_window_id = sdl_get_window_id($main_window);
|
||||||
|
|
||||||
|
// Text-Texturen erstellen
|
||||||
|
function create_text_texture($renderer, $font, $text) {
|
||||||
|
$surface = ttf_render_text_solid($font, $text, 255, 255, 255);
|
||||||
|
if (!$surface) return false;
|
||||||
|
|
||||||
|
$texture = sdl_create_texture_from_surface($renderer, $surface);
|
||||||
|
return $texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hauptfenster Text-Texture
|
||||||
|
$main_text_texture = create_text_texture($main_renderer, $font, 'Fenster öffnen');
|
||||||
|
$main_text_size = ttf_size_text($font, 'Fenster öffnen');
|
||||||
|
|
||||||
|
// Sekundäres Fenster (initial NULL)
|
||||||
|
$second_window = null;
|
||||||
|
$second_window_id = null;
|
||||||
|
$second_renderer = null;
|
||||||
|
$second_text_texture = null;
|
||||||
|
$second_text_size = null;
|
||||||
|
|
||||||
|
// Hilfsfunktion: Prüft ob Punkt in Rechteck ist
|
||||||
|
function point_in_rect($x, $y, $rect) {
|
||||||
|
return $x >= $rect['x'] &&
|
||||||
|
$x <= $rect['x'] + $rect['w'] &&
|
||||||
|
$y >= $rect['y'] &&
|
||||||
|
$y <= $rect['y'] + $rect['h'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zeichnet einen Button
|
||||||
|
function draw_button($renderer, $button, $text_texture, $text_size) {
|
||||||
|
// Button-Hintergrund (grün wenn hovered, blau sonst)
|
||||||
|
if ($button['hovered']) {
|
||||||
|
sdl_rounded_box($renderer,
|
||||||
|
$button['x'], $button['y'],
|
||||||
|
$button['x'] + $button['w'], $button['y'] + $button['h'],
|
||||||
|
15,
|
||||||
|
60, 180, 60, 255
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sdl_rounded_box($renderer,
|
||||||
|
$button['x'], $button['y'],
|
||||||
|
$button['x'] + $button['w'], $button['y'] + $button['h'],
|
||||||
|
15,
|
||||||
|
70, 130, 180, 255
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text zentriert auf Button rendern
|
||||||
|
$text_x = $button['x'] + ($button['w'] - $text_size['w']) / 2;
|
||||||
|
$text_y = $button['y'] + ($button['h'] - $text_size['h']) / 2;
|
||||||
|
|
||||||
|
sdl_render_texture($renderer, $text_texture, [
|
||||||
|
'x' => (int)$text_x,
|
||||||
|
'y' => (int)$text_y,
|
||||||
|
'w' => $text_size['w'],
|
||||||
|
'h' => $text_size['h']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button-Eigenschaften Hauptfenster
|
||||||
|
$main_button = [
|
||||||
|
'x' => 200,
|
||||||
|
'y' => 200,
|
||||||
|
'w' => 240,
|
||||||
|
'h' => 80,
|
||||||
|
'hovered' => false
|
||||||
|
];
|
||||||
|
|
||||||
|
// Button-Eigenschaften zweites Fenster
|
||||||
|
$second_button = [
|
||||||
|
'x' => 100,
|
||||||
|
'y' => 150,
|
||||||
|
'w' => 200,
|
||||||
|
'h' => 80,
|
||||||
|
'hovered' => false
|
||||||
|
];
|
||||||
|
|
||||||
|
echo "Multi-Window Beispiel läuft!\n";
|
||||||
|
echo "Hauptfenster: Klicke auf 'Fenster öffnen' um ein zweites Fenster zu öffnen.\n";
|
||||||
|
echo "Zweites Fenster: Klicke auf 'Schließen' um es zu schließen.\n";
|
||||||
|
|
||||||
|
// Hauptschleife
|
||||||
|
$main_running = true;
|
||||||
|
$second_running = false;
|
||||||
|
|
||||||
|
while ($main_running) {
|
||||||
|
// Events verarbeiten
|
||||||
|
while ($event = sdl_poll_event()) {
|
||||||
|
// Quit-Event schließt alle Fenster
|
||||||
|
if ($event['type'] === SDL_EVENT_QUIT) {
|
||||||
|
$main_running = false;
|
||||||
|
$second_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Window Close Event - prüfe welches Fenster
|
||||||
|
if ($event['type'] === SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
|
||||||
|
if (isset($event['window_id'])) {
|
||||||
|
if ($event['window_id'] === $main_window_id) {
|
||||||
|
echo "Hauptfenster schließen-Anfrage\n";
|
||||||
|
$main_running = false;
|
||||||
|
$second_running = false;
|
||||||
|
} elseif ($second_running && $event['window_id'] === $second_window_id) {
|
||||||
|
echo "Zweites Fenster schließen-Anfrage\n";
|
||||||
|
$second_running = false;
|
||||||
|
$second_window = null;
|
||||||
|
$second_window_id = null;
|
||||||
|
$second_renderer = null;
|
||||||
|
$second_text_texture = null;
|
||||||
|
$second_button['hovered'] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maus-Bewegung
|
||||||
|
if ($event['type'] === SDL_EVENT_MOUSE_MOTION) {
|
||||||
|
if (isset($event['window_id'])) {
|
||||||
|
// Hauptfenster
|
||||||
|
if ($event['window_id'] === $main_window_id) {
|
||||||
|
$main_button['hovered'] = point_in_rect($event['x'], $event['y'], $main_button);
|
||||||
|
}
|
||||||
|
// Zweites Fenster
|
||||||
|
elseif ($second_running && $event['window_id'] === $second_window_id) {
|
||||||
|
$second_button['hovered'] = point_in_rect($event['x'], $event['y'], $second_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maus-Klick
|
||||||
|
if ($event['type'] === SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
||||||
|
if ($event['button'] === SDL_BUTTON_LEFT && isset($event['window_id'])) {
|
||||||
|
// Hauptfenster-Button: Öffne zweites Fenster
|
||||||
|
if ($event['window_id'] === $main_window_id &&
|
||||||
|
point_in_rect($event['x'], $event['y'], $main_button)) {
|
||||||
|
if (!$second_running) {
|
||||||
|
echo "Öffne zweites Fenster...\n";
|
||||||
|
|
||||||
|
$second_window = sdl_create_window('Zweites Fenster', 400, 300);
|
||||||
|
if ($second_window) {
|
||||||
|
$second_window_id = sdl_get_window_id($second_window);
|
||||||
|
$second_renderer = sdl_create_renderer($second_window);
|
||||||
|
if ($second_renderer) {
|
||||||
|
$second_text_texture = create_text_texture($second_renderer, $font, 'Schließen');
|
||||||
|
$second_text_size = ttf_size_text($font, 'Schließen');
|
||||||
|
$second_running = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zweites Fenster-Button: Schließe zweites Fenster
|
||||||
|
if ($second_running && $event['window_id'] === $second_window_id &&
|
||||||
|
point_in_rect($event['x'], $event['y'], $second_button)) {
|
||||||
|
echo "Schließe zweites Fenster...\n";
|
||||||
|
$second_running = false;
|
||||||
|
$second_window = null;
|
||||||
|
$second_window_id = null;
|
||||||
|
$second_renderer = null;
|
||||||
|
$second_text_texture = null;
|
||||||
|
$second_button['hovered'] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hauptfenster rendern
|
||||||
|
sdl_set_render_draw_color($main_renderer, 45, 45, 48, 255);
|
||||||
|
sdl_render_clear($main_renderer);
|
||||||
|
draw_button($main_renderer, $main_button, $main_text_texture, $main_text_size);
|
||||||
|
|
||||||
|
// Info-Text (weißes Rechteck als Platzhalter)
|
||||||
|
sdl_set_render_draw_color($main_renderer, 80, 80, 80, 255);
|
||||||
|
sdl_render_fill_rect($main_renderer, ['x' => 50, 'y' => 50, 'w' => 540, 'h' => 100]);
|
||||||
|
|
||||||
|
sdl_render_present($main_renderer);
|
||||||
|
|
||||||
|
// Zweites Fenster rendern (wenn offen)
|
||||||
|
if ($second_running && $second_renderer) {
|
||||||
|
sdl_set_render_draw_color($second_renderer, 60, 60, 65, 255);
|
||||||
|
sdl_render_clear($second_renderer);
|
||||||
|
draw_button($second_renderer, $second_button, $second_text_texture, $second_text_size);
|
||||||
|
|
||||||
|
// Info-Text
|
||||||
|
sdl_set_render_draw_color($second_renderer, 100, 100, 100, 255);
|
||||||
|
sdl_render_fill_rect($second_renderer, ['x' => 50, 'y' => 50, 'w' => 300, 'h' => 60]);
|
||||||
|
|
||||||
|
sdl_render_present($second_renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPU schonen
|
||||||
|
sdl_delay(16); // ~60 FPS
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Programm beendet.\n";
|
||||||
|
sdl_quit();
|
||||||
@ -6,4 +6,10 @@ extern zend_module_entry sdl3_module_entry;
|
|||||||
|
|
||||||
#define PHP_SDL3_VERSION "0.1.0"
|
#define PHP_SDL3_VERSION "0.1.0"
|
||||||
|
|
||||||
|
// Resource handles exportieren, damit sie in anderen Modulen verfügbar sind
|
||||||
|
extern int le_sdl_window;
|
||||||
|
extern int le_sdl_renderer;
|
||||||
|
extern int le_sdl_texture;
|
||||||
|
extern int le_sdl_surface;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
355
php-sdl3/sdl3.c
355
php-sdl3/sdl3.c
@ -6,13 +6,17 @@
|
|||||||
#include "php.h"
|
#include "php.h"
|
||||||
#include "php_sdl3.h"
|
#include "php_sdl3.h"
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
|
#include "sdl3_image.h"
|
||||||
|
#include "sdl3_ttf.h"
|
||||||
|
#include "sdl3_events.h"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_gfx/SDL3_gfxPrimitives.h>
|
#include <SDL3_gfx/SDL3_gfxPrimitives.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
// Resource handles
|
// Resource handles (nicht static, damit sie in anderen Modulen verfügbar sind)
|
||||||
static int le_sdl_window;
|
int le_sdl_window;
|
||||||
static int le_sdl_renderer;
|
int le_sdl_renderer;
|
||||||
|
int le_sdl_texture;
|
||||||
|
|
||||||
// Destructor for window resource
|
// Destructor for window resource
|
||||||
static void sdl_window_dtor(zend_resource *rsrc) {
|
static void sdl_window_dtor(zend_resource *rsrc) {
|
||||||
@ -30,9 +34,41 @@ static void sdl_renderer_dtor(zend_resource *rsrc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destructor for texture resource
|
||||||
|
static void sdl_texture_dtor(zend_resource *rsrc) {
|
||||||
|
SDL_Texture *tex = (SDL_Texture *)rsrc->ptr;
|
||||||
|
if (tex) {
|
||||||
|
SDL_DestroyTexture(tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PHP_MINIT_FUNCTION(sdl3) {
|
PHP_MINIT_FUNCTION(sdl3) {
|
||||||
le_sdl_window = zend_register_list_destructors_ex(sdl_window_dtor, NULL, "SDL_Window", module_number);
|
le_sdl_window = zend_register_list_destructors_ex(sdl_window_dtor, NULL, "SDL_Window", module_number);
|
||||||
le_sdl_renderer = zend_register_list_destructors_ex(sdl_renderer_dtor, NULL, "SDL_Renderer", module_number);
|
le_sdl_renderer = zend_register_list_destructors_ex(sdl_renderer_dtor, NULL, "SDL_Renderer", module_number);
|
||||||
|
le_sdl_texture = zend_register_list_destructors_ex(sdl_texture_dtor, NULL, "SDL_Texture", module_number);
|
||||||
|
|
||||||
|
// Registriere SDL3_image und SDL3_ttf Resources
|
||||||
|
sdl3_image_register_resources(module_number);
|
||||||
|
sdl3_ttf_register_resources(module_number);
|
||||||
|
|
||||||
|
// Registriere Event-Konstanten
|
||||||
|
sdl3_events_register_constants(module_number);
|
||||||
|
|
||||||
|
// SDL Init Flags
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_INIT_VIDEO", SDL_INIT_VIDEO, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_INIT_AUDIO", SDL_INIT_AUDIO, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_INIT_EVENTS", SDL_INIT_EVENTS, CONST_CS | CONST_PERSISTENT);
|
||||||
|
|
||||||
|
// SDL Window Flags
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_WINDOW_FULLSCREEN", SDL_WINDOW_FULLSCREEN, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_WINDOW_OPENGL", SDL_WINDOW_OPENGL, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_WINDOW_HIDDEN", SDL_WINDOW_HIDDEN, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_WINDOW_BORDERLESS", SDL_WINDOW_BORDERLESS, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_WINDOW_RESIZABLE", SDL_WINDOW_RESIZABLE, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_WINDOW_MINIMIZED", SDL_WINDOW_MINIMIZED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_WINDOW_MAXIMIZED", SDL_WINDOW_MAXIMIZED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_WINDOW_HIGH_PIXEL_DENSITY", SDL_WINDOW_HIGH_PIXEL_DENSITY, CONST_CS | CONST_PERSISTENT);
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,19 +90,60 @@ PHP_FUNCTION(sdl_quit) {
|
|||||||
PHP_FUNCTION(sdl_create_window) {
|
PHP_FUNCTION(sdl_create_window) {
|
||||||
char *title;
|
char *title;
|
||||||
size_t title_len;
|
size_t title_len;
|
||||||
zend_long w, h;
|
zend_long w, h, flags = 0;
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll", &title, &title_len, &w, &h) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll|l", &title, &title_len, &w, &h, &flags) == FAILURE) {
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Window *win = SDL_CreateWindow(title, (int)w, (int)h, 0);
|
SDL_Window *win = SDL_CreateWindow(title, (int)w, (int)h, (SDL_WindowFlags)flags);
|
||||||
if (!win) {
|
if (!win) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
RETURN_RES(zend_register_resource(win, le_sdl_window));
|
RETURN_RES(zend_register_resource(win, le_sdl_window));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_destroy_window) {
|
||||||
|
zval *win_res;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &win_res) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will call the destructor and free the resource
|
||||||
|
zend_list_close(Z_RES_P(win_res));
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_destroy_renderer) {
|
||||||
|
zval *ren_res;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &ren_res) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will call the destructor and free the resource
|
||||||
|
zend_list_close(Z_RES_P(ren_res));
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_get_window_id) {
|
||||||
|
zval *win_res;
|
||||||
|
SDL_Window *win;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &win_res) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
win = (SDL_Window *)zend_fetch_resource(Z_RES_P(win_res), "SDL_Window", le_sdl_window);
|
||||||
|
if (!win) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_WindowID window_id = SDL_GetWindowID(win);
|
||||||
|
RETURN_LONG(window_id);
|
||||||
|
}
|
||||||
|
|
||||||
PHP_FUNCTION(sdl_create_renderer) {
|
PHP_FUNCTION(sdl_create_renderer) {
|
||||||
zval *win_res;
|
zval *win_res;
|
||||||
SDL_Window *win;
|
SDL_Window *win;
|
||||||
@ -185,6 +262,79 @@ PHP_FUNCTION(sdl_get_error) {
|
|||||||
RETURN_STRING(error);
|
RETURN_STRING(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_create_texture_from_surface) {
|
||||||
|
zval *ren_res, *surf_res;
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
SDL_Surface *surface;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &ren_res, &surf_res) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer = (SDL_Renderer *)zend_fetch_resource(Z_RES_P(ren_res), "SDL_Renderer", le_sdl_renderer);
|
||||||
|
if (!renderer) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
surface = (SDL_Surface *)zend_fetch_resource(Z_RES_P(surf_res), "SDL_Surface", le_sdl_surface);
|
||||||
|
if (!surface) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||||
|
if (!texture) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Failed to create texture: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_RES(zend_register_resource(texture, le_sdl_texture));
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_render_texture) {
|
||||||
|
zval *ren_res, *tex_res;
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
zval *dst_arr = NULL;
|
||||||
|
HashTable *dst_ht;
|
||||||
|
zval *data;
|
||||||
|
zend_long x, y, w, h;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|a", &ren_res, &tex_res, &dst_arr) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer = (SDL_Renderer *)zend_fetch_resource(Z_RES_P(ren_res), "SDL_Renderer", le_sdl_renderer);
|
||||||
|
if (!renderer) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture = (SDL_Texture *)zend_fetch_resource(Z_RES_P(tex_res), "SDL_Texture", le_sdl_texture);
|
||||||
|
if (!texture) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst_arr != NULL) {
|
||||||
|
// Mit Zielrechteck
|
||||||
|
dst_ht = Z_ARRVAL_P(dst_arr);
|
||||||
|
if (((data = zend_hash_str_find(dst_ht, "x", 1)) != NULL && (x = zval_get_long(data), true)) &&
|
||||||
|
((data = zend_hash_str_find(dst_ht, "y", 1)) != NULL && (y = zval_get_long(data), true)) &&
|
||||||
|
((data = zend_hash_str_find(dst_ht, "w", 1)) != NULL && (w = zval_get_long(data), true)) &&
|
||||||
|
((data = zend_hash_str_find(dst_ht, "h", 1)) != NULL && (h = zval_get_long(data), true))) {
|
||||||
|
|
||||||
|
SDL_FRect dstrect = {(float)x, (float)y, (float)w, (float)h};
|
||||||
|
SDL_RenderTexture(renderer, texture, NULL, &dstrect);
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_throw_error(NULL, "Invalid destination rectangle. Expected ['x'=>int, 'y'=>int, 'w'=>int, 'h'=>int]");
|
||||||
|
RETURN_THROWS();
|
||||||
|
} else {
|
||||||
|
// Ohne Zielrechteck - volle Größe
|
||||||
|
SDL_RenderTexture(renderer, texture, NULL, NULL);
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PHP_FUNCTION(sdl_rounded_box)
|
PHP_FUNCTION(sdl_rounded_box)
|
||||||
{
|
{
|
||||||
zval *ren_res;
|
zval *ren_res;
|
||||||
@ -237,18 +387,40 @@ PHP_FUNCTION(sdl_rounded_box_ex)
|
|||||||
int r_right = (rad_tr > rad_br) ? rad_tr : rad_br;
|
int r_right = (rad_tr > rad_br) ? rad_tr : rad_br;
|
||||||
|
|
||||||
// 1) center vertical band (zwischen links und rechts Radien), ganze Höhe
|
// 1) center vertical band (zwischen links und rechts Radien), ganze Höhe
|
||||||
SDL_FRect center = { x1 + rad_tl, y1, x2 - x1-rad_tl-rad_br, y2-y1 };
|
SDL_FRect center = { x1 + r_left, y1, x2 - x1-r_left-r_right, y2-y1 };
|
||||||
if (center.w > 0 && center.h > 0) SDL_RenderFillRect(ren, ¢er);
|
if (center.w > 0 && center.h > 0) SDL_RenderFillRect(ren, ¢er);
|
||||||
|
|
||||||
// 2) left vertical rectangle (zwischen oberen und unteren Ecken links)
|
// 2) left vertical rectangle (zwischen oberen und unteren Ecken links)
|
||||||
SDL_FRect leftRect = { x1, y1 + rad_tl, rad_bl, y2-rad_tl-rad_bl-y1 };
|
SDL_FRect leftRect = { x1, y1 + rad_tl, r_left, y2 - y1 - rad_tl - rad_bl };
|
||||||
if (leftRect.w > 0 && leftRect.h > 0) SDL_RenderFillRect(ren, &leftRect);
|
if (leftRect.w > 0 && leftRect.h > 0) SDL_RenderFillRect(ren, &leftRect);
|
||||||
|
|
||||||
// 3) right vertical rectangle (zwischen oberen und unteren Ecken rechts)
|
// 3) right vertical rectangle (zwischen oberen und unteren Ecken rechts)
|
||||||
SDL_FRect rightRect = { x2 - r_right, y1 + rad_tr, r_right, y2-y1-rad_tr - rad_br };
|
SDL_FRect rightRect = { x2 - r_right, y1 + rad_tr, r_right, y2 - y1 - rad_tr - rad_br };
|
||||||
if (rightRect.w > 0 && rightRect.h > 0) SDL_RenderFillRect(ren, &rightRect);
|
if (rightRect.w > 0 && rightRect.h > 0) SDL_RenderFillRect(ren, &rightRect);
|
||||||
|
|
||||||
// 4) vier gefüllte Viertel-Kreise in den Ecken
|
// 4) Horizontale Füllrechtecke für Lücken zwischen Ecken und vertikalen Rechtecken
|
||||||
|
// Oben links: wenn rad_tl < r_left
|
||||||
|
if (rad_tl < r_left) {
|
||||||
|
SDL_FRect topLeft = { x1 + rad_tl, y1, r_left - rad_tl, rad_tl };
|
||||||
|
if (topLeft.w > 0 && topLeft.h > 0) SDL_RenderFillRect(ren, &topLeft);
|
||||||
|
}
|
||||||
|
// Oben rechts: wenn rad_tr < r_right
|
||||||
|
if (rad_tr < r_right) {
|
||||||
|
SDL_FRect topRight = { x2 - r_right, y1, r_right - rad_tr, rad_tr };
|
||||||
|
if (topRight.w > 0 && topRight.h > 0) SDL_RenderFillRect(ren, &topRight);
|
||||||
|
}
|
||||||
|
// Unten rechts: wenn rad_br < r_right
|
||||||
|
if (rad_br < r_right) {
|
||||||
|
SDL_FRect bottomRight = { x2 - r_right, y2 - rad_br, r_right - rad_br, rad_br };
|
||||||
|
if (bottomRight.w > 0 && bottomRight.h > 0) SDL_RenderFillRect(ren, &bottomRight);
|
||||||
|
}
|
||||||
|
// Unten links: wenn rad_bl < r_left
|
||||||
|
if (rad_bl < r_left) {
|
||||||
|
SDL_FRect bottomLeft = { x1 + rad_bl, y2 - rad_bl, r_left - rad_bl, rad_bl };
|
||||||
|
if (bottomLeft.w > 0 && bottomLeft.h > 0) SDL_RenderFillRect(ren, &bottomLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) vier gefüllte Viertel-Kreise in den Ecken
|
||||||
if (rad_tl > 0) filled_quarter_circle(ren, x1 + rad_tl, y1 + rad_tl, rad_tl, 0);
|
if (rad_tl > 0) filled_quarter_circle(ren, x1 + rad_tl, y1 + rad_tl, rad_tl, 0);
|
||||||
if (rad_tr > 0) filled_quarter_circle(ren, x2 - rad_tr, y1 + rad_tr, rad_tr, 1);
|
if (rad_tr > 0) filled_quarter_circle(ren, x2 - rad_tr, y1 + rad_tr, rad_tr, 1);
|
||||||
if (rad_br > 0) filled_quarter_circle(ren, x2 - rad_br, y2- rad_br, rad_br, 2);
|
if (rad_br > 0) filled_quarter_circle(ren, x2 - rad_br, y2- rad_br, rad_br, 2);
|
||||||
@ -257,6 +429,99 @@ PHP_FUNCTION(sdl_rounded_box_ex)
|
|||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_set_render_clip_rect) {
|
||||||
|
zval *ren_res;
|
||||||
|
SDL_Renderer *ren;
|
||||||
|
zval *rect_arr = NULL;
|
||||||
|
HashTable *rect_ht;
|
||||||
|
zval *data;
|
||||||
|
zend_long x, y, w, h;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|a!", &ren_res, &rect_arr) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
ren = (SDL_Renderer *)zend_fetch_resource(Z_RES_P(ren_res), "SDL_Renderer", le_sdl_renderer);
|
||||||
|
if (!ren) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rect_arr == NULL || Z_TYPE_P(rect_arr) == IS_NULL) {
|
||||||
|
// Disable clipping
|
||||||
|
SDL_SetRenderClipRect(ren, NULL);
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect_ht = Z_ARRVAL_P(rect_arr);
|
||||||
|
if (((data = zend_hash_str_find(rect_ht, "x", 1)) != NULL && (x = zval_get_long(data), true)) &&
|
||||||
|
((data = zend_hash_str_find(rect_ht, "y", 1)) != NULL && (y = zval_get_long(data), true)) &&
|
||||||
|
((data = zend_hash_str_find(rect_ht, "w", 1)) != NULL && (w = zval_get_long(data), true)) &&
|
||||||
|
((data = zend_hash_str_find(rect_ht, "h", 1)) != NULL && (h = zval_get_long(data), true))) {
|
||||||
|
|
||||||
|
SDL_Rect rect = {(int)x, (int)y, (int)w, (int)h};
|
||||||
|
SDL_SetRenderClipRect(ren, &rect);
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_throw_error(NULL, "Invalid rectangle array passed to sdl_set_render_clip_rect. Expected ['x'=>int, 'y'=>int, 'w'=>int, 'h'=>int] or null");
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_get_window_size) {
|
||||||
|
zval *win_res;
|
||||||
|
SDL_Window *win;
|
||||||
|
int w, h;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &win_res) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
win = (SDL_Window *)zend_fetch_resource(Z_RES_P(win_res), "SDL_Window", le_sdl_window);
|
||||||
|
if (!win) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GetWindowSize(win, &w, &h);
|
||||||
|
|
||||||
|
array_init(return_value);
|
||||||
|
add_index_long(return_value, 0, w);
|
||||||
|
add_index_long(return_value, 1, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_start_text_input) {
|
||||||
|
zval *win_res;
|
||||||
|
SDL_Window *win;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &win_res) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
win = (SDL_Window *)zend_fetch_resource(Z_RES_P(win_res), "SDL_Window", le_sdl_window);
|
||||||
|
if (!win) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_StartTextInput(win);
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_stop_text_input) {
|
||||||
|
zval *win_res;
|
||||||
|
SDL_Window *win;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &win_res) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
win = (SDL_Window *)zend_fetch_resource(Z_RES_P(win_res), "SDL_Window", le_sdl_window);
|
||||||
|
if (!win) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_StopTextInput(win);
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_init, 0, 0, 1)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_init, 0, 0, 1)
|
||||||
ZEND_ARG_INFO(0, flags)
|
ZEND_ARG_INFO(0, flags)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
@ -268,6 +533,19 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_create_window, 0, 0, 3)
|
|||||||
ZEND_ARG_INFO(0, title)
|
ZEND_ARG_INFO(0, title)
|
||||||
ZEND_ARG_INFO(0, w)
|
ZEND_ARG_INFO(0, w)
|
||||||
ZEND_ARG_INFO(0, h)
|
ZEND_ARG_INFO(0, h)
|
||||||
|
ZEND_ARG_INFO(0, flags)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_destroy_window, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, window)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_destroy_renderer, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, renderer)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_get_window_id, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, window)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_create_renderer, 0, 0, 1)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_create_renderer, 0, 0, 1)
|
||||||
@ -302,6 +580,17 @@ ZEND_END_ARG_INFO()
|
|||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_get_error, 0, 0, 0)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_get_error, 0, 0, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_create_texture_from_surface, 0, 0, 2)
|
||||||
|
ZEND_ARG_INFO(0, renderer)
|
||||||
|
ZEND_ARG_INFO(0, surface)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_render_texture, 0, 0, 2)
|
||||||
|
ZEND_ARG_INFO(0, renderer)
|
||||||
|
ZEND_ARG_INFO(0, texture)
|
||||||
|
ZEND_ARG_INFO(0, dstrect)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_rounded_box, 0, 0, 10)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_rounded_box, 0, 0, 10)
|
||||||
ZEND_ARG_INFO(0, renderer)
|
ZEND_ARG_INFO(0, renderer)
|
||||||
ZEND_ARG_INFO(0, x1)
|
ZEND_ARG_INFO(0, x1)
|
||||||
@ -331,10 +620,31 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_rounded_box_ex, 0, 0, 13)
|
|||||||
ZEND_ARG_INFO(0, a)
|
ZEND_ARG_INFO(0, a)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_set_render_clip_rect, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, renderer)
|
||||||
|
ZEND_ARG_INFO(0, rect)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_get_window_size, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, window)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_start_text_input, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, window)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_stop_text_input, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, window)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
const zend_function_entry sdl3_functions[] = {
|
const zend_function_entry sdl3_functions[] = {
|
||||||
|
// SDL3 Core
|
||||||
PHP_FE(sdl_init, arginfo_sdl_init)
|
PHP_FE(sdl_init, arginfo_sdl_init)
|
||||||
PHP_FE(sdl_quit, arginfo_sdl_quit)
|
PHP_FE(sdl_quit, arginfo_sdl_quit)
|
||||||
PHP_FE(sdl_create_window, arginfo_sdl_create_window)
|
PHP_FE(sdl_create_window, arginfo_sdl_create_window)
|
||||||
|
PHP_FE(sdl_destroy_window, arginfo_sdl_destroy_window)
|
||||||
|
PHP_FE(sdl_destroy_renderer, arginfo_sdl_destroy_renderer)
|
||||||
|
PHP_FE(sdl_get_window_id, arginfo_sdl_get_window_id)
|
||||||
PHP_FE(sdl_create_renderer, arginfo_sdl_create_renderer)
|
PHP_FE(sdl_create_renderer, arginfo_sdl_create_renderer)
|
||||||
PHP_FE(sdl_set_render_draw_color, arginfo_sdl_set_render_draw_color)
|
PHP_FE(sdl_set_render_draw_color, arginfo_sdl_set_render_draw_color)
|
||||||
PHP_FE(sdl_render_clear, arginfo_sdl_render_clear)
|
PHP_FE(sdl_render_clear, arginfo_sdl_render_clear)
|
||||||
@ -342,8 +652,33 @@ const zend_function_entry sdl3_functions[] = {
|
|||||||
PHP_FE(sdl_render_present, arginfo_sdl_render_present)
|
PHP_FE(sdl_render_present, arginfo_sdl_render_present)
|
||||||
PHP_FE(sdl_delay, arginfo_sdl_delay)
|
PHP_FE(sdl_delay, arginfo_sdl_delay)
|
||||||
PHP_FE(sdl_get_error, arginfo_sdl_get_error)
|
PHP_FE(sdl_get_error, arginfo_sdl_get_error)
|
||||||
|
PHP_FE(sdl_create_texture_from_surface, arginfo_sdl_create_texture_from_surface)
|
||||||
|
PHP_FE(sdl_render_texture, arginfo_sdl_render_texture)
|
||||||
PHP_FE(sdl_rounded_box, arginfo_sdl_rounded_box)
|
PHP_FE(sdl_rounded_box, arginfo_sdl_rounded_box)
|
||||||
PHP_FE(sdl_rounded_box_ex, arginfo_sdl_rounded_box_ex)
|
PHP_FE(sdl_rounded_box_ex, arginfo_sdl_rounded_box_ex)
|
||||||
|
PHP_FE(sdl_set_render_clip_rect, arginfo_sdl_set_render_clip_rect)
|
||||||
|
PHP_FE(sdl_get_window_size, arginfo_sdl_get_window_size)
|
||||||
|
PHP_FE(sdl_start_text_input, arginfo_sdl_start_text_input)
|
||||||
|
PHP_FE(sdl_stop_text_input, arginfo_sdl_stop_text_input)
|
||||||
|
|
||||||
|
// SDL3_image
|
||||||
|
PHP_FE(img_load, arginfo_img_load)
|
||||||
|
PHP_FE(img_load_texture, arginfo_img_load_texture)
|
||||||
|
|
||||||
|
// SDL3_ttf
|
||||||
|
PHP_FE(ttf_init, arginfo_ttf_init)
|
||||||
|
PHP_FE(ttf_open_font, arginfo_ttf_open_font)
|
||||||
|
PHP_FE(ttf_close_font, arginfo_ttf_close_font)
|
||||||
|
PHP_FE(ttf_render_text_solid, arginfo_ttf_render_text_solid)
|
||||||
|
PHP_FE(ttf_render_text_blended, arginfo_ttf_render_text_blended)
|
||||||
|
PHP_FE(ttf_render_text_shaded, arginfo_ttf_render_text_shaded)
|
||||||
|
PHP_FE(ttf_size_text, arginfo_ttf_size_text)
|
||||||
|
|
||||||
|
// SDL3 Events
|
||||||
|
PHP_FE(sdl_poll_event, arginfo_sdl_poll_event)
|
||||||
|
PHP_FE(sdl_wait_event, arginfo_sdl_wait_event)
|
||||||
|
PHP_FE(sdl_wait_event_timeout, arginfo_sdl_wait_event_timeout)
|
||||||
|
|
||||||
PHP_FE_END
|
PHP_FE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -91,4 +91,7 @@ sdl3.lo: /home/thomas/projekte/phpnative/framework/php-sdl3/sdl3.c \
|
|||||||
/usr/local/include/php/Zend/zend_constants.h \
|
/usr/local/include/php/Zend/zend_constants.h \
|
||||||
/usr/local/include/php/main/php_reentrancy.h \
|
/usr/local/include/php/main/php_reentrancy.h \
|
||||||
/home/thomas/projekte/phpnative/framework/php-sdl3/php_sdl3.h \
|
/home/thomas/projekte/phpnative/framework/php-sdl3/php_sdl3.h \
|
||||||
/home/thomas/projekte/phpnative/framework/php-sdl3/helper.h
|
/home/thomas/projekte/phpnative/framework/php-sdl3/helper.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_image.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_ttf.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_events.h
|
||||||
|
|||||||
@ -14,7 +14,7 @@ library_names='sdl3.so sdl3.so sdl3.so'
|
|||||||
old_library=''
|
old_library=''
|
||||||
|
|
||||||
# Libraries that this one depends upon.
|
# Libraries that this one depends upon.
|
||||||
dependency_libs=' -L/usr/local/lib -lSDL3_gfx -lSDL3'
|
dependency_libs=' -L/usr/local/lib -lSDL3_gfx -lSDL3_image -lSDL3_ttf -lSDL3'
|
||||||
|
|
||||||
# Version information for sdl3.
|
# Version information for sdl3.
|
||||||
current=0
|
current=0
|
||||||
|
|||||||
175
php-sdl3/sdl3_events.c
Normal file
175
php-sdl3/sdl3_events.c
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "php_sdl3.h"
|
||||||
|
#include "sdl3_events.h"
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
// Registriert Event-Konstanten
|
||||||
|
void sdl3_events_register_constants(int module_number) {
|
||||||
|
// Event Types
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_QUIT", SDL_EVENT_QUIT, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_CLOSE_REQUESTED", SDL_EVENT_WINDOW_CLOSE_REQUESTED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
|
||||||
|
// Window Events
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_SHOWN", SDL_EVENT_WINDOW_SHOWN, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_HIDDEN", SDL_EVENT_WINDOW_HIDDEN, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_EXPOSED", SDL_EVENT_WINDOW_EXPOSED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_MOVED", SDL_EVENT_WINDOW_MOVED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_RESIZED", SDL_EVENT_WINDOW_RESIZED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_MINIMIZED", SDL_EVENT_WINDOW_MINIMIZED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_MAXIMIZED", SDL_EVENT_WINDOW_MAXIMIZED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_RESTORED", SDL_EVENT_WINDOW_RESTORED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_MOUSE_ENTER", SDL_EVENT_WINDOW_MOUSE_ENTER, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_MOUSE_LEAVE", SDL_EVENT_WINDOW_MOUSE_LEAVE, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_FOCUS_GAINED", SDL_EVENT_WINDOW_FOCUS_GAINED, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_WINDOW_FOCUS_LOST", SDL_EVENT_WINDOW_FOCUS_LOST, CONST_CS | CONST_PERSISTENT);
|
||||||
|
|
||||||
|
// Keyboard Events
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_KEY_DOWN", SDL_EVENT_KEY_DOWN, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_KEY_UP", SDL_EVENT_KEY_UP, CONST_CS | CONST_PERSISTENT);
|
||||||
|
|
||||||
|
// Mouse Events
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_MOUSE_MOTION", SDL_EVENT_MOUSE_MOTION, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_MOUSE_BUTTON_DOWN", SDL_EVENT_MOUSE_BUTTON_DOWN, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_MOUSE_BUTTON_UP", SDL_EVENT_MOUSE_BUTTON_UP, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_MOUSE_WHEEL", SDL_EVENT_MOUSE_WHEEL, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_EVENT_TEXT_INPUT", SDL_EVENT_TEXT_INPUT, CONST_CS | CONST_PERSISTENT);
|
||||||
|
|
||||||
|
// Mouse Buttons
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_BUTTON_LEFT", SDL_BUTTON_LEFT, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_BUTTON_MIDDLE", SDL_BUTTON_MIDDLE, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_BUTTON_RIGHT", SDL_BUTTON_RIGHT, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_BUTTON_X1", SDL_BUTTON_X1, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDL_BUTTON_X2", SDL_BUTTON_X2, CONST_CS | CONST_PERSISTENT);
|
||||||
|
|
||||||
|
// Common Keycodes
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_RETURN", SDLK_RETURN, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_ESCAPE", SDLK_ESCAPE, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_BACKSPACE", SDLK_BACKSPACE, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_TAB", SDLK_TAB, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_DELETE", SDLK_DELETE, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_LEFT", SDLK_LEFT, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_RIGHT", SDLK_RIGHT, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_UP", SDLK_UP, CONST_CS | CONST_PERSISTENT);
|
||||||
|
REGISTER_LONG_CONSTANT("SDLK_DOWN", SDLK_DOWN, CONST_CS | CONST_PERSISTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_poll_event) {
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
if (!SDL_PollEvent(&event)) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event als Array zurückgeben
|
||||||
|
array_init(return_value);
|
||||||
|
add_assoc_long(return_value, "type", event.type);
|
||||||
|
add_assoc_long(return_value, "timestamp", event.common.timestamp);
|
||||||
|
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_EVENT_QUIT:
|
||||||
|
// Keine zusätzlichen Daten
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||||
|
case SDL_EVENT_WINDOW_SHOWN:
|
||||||
|
case SDL_EVENT_WINDOW_HIDDEN:
|
||||||
|
case SDL_EVENT_WINDOW_EXPOSED:
|
||||||
|
case SDL_EVENT_WINDOW_MOVED:
|
||||||
|
case SDL_EVENT_WINDOW_RESIZED:
|
||||||
|
case SDL_EVENT_WINDOW_MINIMIZED:
|
||||||
|
case SDL_EVENT_WINDOW_MAXIMIZED:
|
||||||
|
case SDL_EVENT_WINDOW_RESTORED:
|
||||||
|
case SDL_EVENT_WINDOW_MOUSE_ENTER:
|
||||||
|
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||||
|
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||||
|
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||||
|
add_assoc_long(return_value, "window_id", event.window.windowID);
|
||||||
|
if (event.type == SDL_EVENT_WINDOW_MOVED || event.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||||
|
add_assoc_long(return_value, "data1", event.window.data1);
|
||||||
|
add_assoc_long(return_value, "data2", event.window.data2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_KEY_DOWN:
|
||||||
|
case SDL_EVENT_KEY_UP:
|
||||||
|
add_assoc_long(return_value, "window_id", event.key.windowID);
|
||||||
|
add_assoc_long(return_value, "scancode", event.key.scancode);
|
||||||
|
add_assoc_long(return_value, "keycode", event.key.key);
|
||||||
|
add_assoc_long(return_value, "mod", event.key.mod);
|
||||||
|
add_assoc_bool(return_value, "repeat", event.key.repeat);
|
||||||
|
add_assoc_bool(return_value, "down", event.key.down);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
|
add_assoc_long(return_value, "window_id", event.motion.windowID);
|
||||||
|
add_assoc_long(return_value, "which", event.motion.which);
|
||||||
|
add_assoc_double(return_value, "x", event.motion.x);
|
||||||
|
add_assoc_double(return_value, "y", event.motion.y);
|
||||||
|
add_assoc_double(return_value, "xrel", event.motion.xrel);
|
||||||
|
add_assoc_double(return_value, "yrel", event.motion.yrel);
|
||||||
|
add_assoc_long(return_value, "state", event.motion.state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||||
|
add_assoc_long(return_value, "window_id", event.button.windowID);
|
||||||
|
add_assoc_long(return_value, "which", event.button.which);
|
||||||
|
add_assoc_long(return_value, "button", event.button.button);
|
||||||
|
add_assoc_bool(return_value, "down", event.button.down);
|
||||||
|
add_assoc_long(return_value, "clicks", event.button.clicks);
|
||||||
|
add_assoc_double(return_value, "x", event.button.x);
|
||||||
|
add_assoc_double(return_value, "y", event.button.y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_MOUSE_WHEEL:
|
||||||
|
add_assoc_long(return_value, "window_id", event.wheel.windowID);
|
||||||
|
add_assoc_long(return_value, "which", event.wheel.which);
|
||||||
|
add_assoc_double(return_value, "x", event.wheel.x);
|
||||||
|
add_assoc_double(return_value, "y", event.wheel.y);
|
||||||
|
add_assoc_long(return_value, "direction", event.wheel.direction);
|
||||||
|
add_assoc_double(return_value, "mouse_x", event.wheel.mouse_x);
|
||||||
|
add_assoc_double(return_value, "mouse_y", event.wheel.mouse_y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_TEXT_INPUT:
|
||||||
|
add_assoc_long(return_value, "window_id", event.text.windowID);
|
||||||
|
add_assoc_string(return_value, "text", event.text.text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_wait_event) {
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
if (!SDL_WaitEvent(&event)) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "SDL_WaitEvent failed: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event als Array zurückgeben (gleiche Logik wie poll_event)
|
||||||
|
array_init(return_value);
|
||||||
|
add_assoc_long(return_value, "type", event.type);
|
||||||
|
add_assoc_long(return_value, "timestamp", event.common.timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(sdl_wait_event_timeout) {
|
||||||
|
zend_long timeout_ms;
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &timeout_ms) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SDL_WaitEventTimeout(&event, (int)timeout_ms)) {
|
||||||
|
RETURN_FALSE; // Timeout oder Fehler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event als Array zurückgeben
|
||||||
|
array_init(return_value);
|
||||||
|
add_assoc_long(return_value, "type", event.type);
|
||||||
|
add_assoc_long(return_value, "timestamp", event.common.timestamp);
|
||||||
|
}
|
||||||
95
php-sdl3/sdl3_events.dep
Normal file
95
php-sdl3/sdl3_events.dep
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
sdl3_events.lo: \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_events.c \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/config.h \
|
||||||
|
/usr/local/include/php/main/php.h \
|
||||||
|
/usr/local/include/php/main/php_version.h \
|
||||||
|
/usr/local/include/php/Zend/zend.h \
|
||||||
|
/usr/local/include/php/Zend/zend_types.h \
|
||||||
|
/usr/local/include/php/Zend/zend_portability.h \
|
||||||
|
/usr/local/include/php/Zend/zend_config.h \
|
||||||
|
/usr/local/include/php/main/../main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/../TSRM/TSRM.h \
|
||||||
|
/usr/local/include/php/main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/zend_range_check.h \
|
||||||
|
/usr/local/include/php/Zend/zend_long.h \
|
||||||
|
/usr/local/include/php/Zend/zend_map_ptr.h \
|
||||||
|
/usr/local/include/php/Zend/zend_errors.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc_sizes.h \
|
||||||
|
/usr/local/include/php/Zend/zend_llist.h \
|
||||||
|
/usr/local/include/php/Zend/zend_string.h \
|
||||||
|
/usr/local/include/php/Zend/zend_gc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hrtime.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hash.h \
|
||||||
|
/usr/local/include/php/Zend/zend_sort.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ast.h \
|
||||||
|
/usr/local/include/php/Zend/zend_variables.h \
|
||||||
|
/usr/local/include/php/Zend/zend_iterators.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stream.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_str_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_string_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_signal.h \
|
||||||
|
/usr/local/include/php/Zend/zend_max_execution_timer.h \
|
||||||
|
/usr/local/include/php/Zend/zend_object_handlers.h \
|
||||||
|
/usr/local/include/php/Zend/zend_property_hooks.h \
|
||||||
|
/usr/local/include/php/Zend/zend_lazy_objects.h \
|
||||||
|
/usr/local/include/php/Zend/zend_types.h \
|
||||||
|
/usr/local/include/php/Zend/zend_operators.h \
|
||||||
|
/usr/local/include/php/Zend/zend_strtod.h \
|
||||||
|
/usr/local/include/php/Zend/zend_multiply.h \
|
||||||
|
/usr/local/include/php/Zend/zend_sort.h \
|
||||||
|
/usr/local/include/php/main/php_compat.h \
|
||||||
|
/usr/local/include/php/main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/zend_API.h \
|
||||||
|
/usr/local/include/php/Zend/zend_modules.h \
|
||||||
|
/usr/local/include/php/Zend/zend.h \
|
||||||
|
/usr/local/include/php/Zend/zend_compile.h \
|
||||||
|
/usr/local/include/php/Zend/zend_frameless_function.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals_macros.h \
|
||||||
|
/usr/local/include/php/Zend/zend_atomic.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ptr_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_objects.h \
|
||||||
|
/usr/local/include/php/Zend/zend_objects_API.h \
|
||||||
|
/usr/local/include/php/Zend/zend_float.h \
|
||||||
|
/usr/local/include/php/Zend/zend_multibyte.h \
|
||||||
|
/usr/local/include/php/Zend/zend_arena.h \
|
||||||
|
/usr/local/include/php/Zend/zend_call_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_vm_opcodes.h \
|
||||||
|
/usr/local/include/php/Zend/zend_build.h \
|
||||||
|
/usr/local/include/php/Zend/zend_list.h \
|
||||||
|
/usr/local/include/php/Zend/zend_execute.h \
|
||||||
|
/usr/local/include/php/Zend/zend_type_info.h \
|
||||||
|
/usr/local/include/php/main/build-defs.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hash.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stack.h \
|
||||||
|
/usr/local/include/php/main/snprintf.h \
|
||||||
|
/usr/local/include/php/main/spprintf.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_str_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_string_public.h \
|
||||||
|
/usr/local/include/php/main/php_syslog.h \
|
||||||
|
/usr/local/include/php/main/php.h \
|
||||||
|
/usr/local/include/php/main/php_output.h \
|
||||||
|
/usr/local/include/php/main/php_streams.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stream.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_context.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_filter_api.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_transport.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_plain_wrapper.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_glob_wrapper.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_userspace.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_mmap.h \
|
||||||
|
/usr/local/include/php/main/php_memory_streams.h \
|
||||||
|
/usr/local/include/php/main/fopen_wrappers.h \
|
||||||
|
/usr/local/include/php/main/php_globals.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals.h \
|
||||||
|
/usr/local/include/php/main/php_ini.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ini.h \
|
||||||
|
/usr/local/include/php/Zend/zend_virtual_cwd.h \
|
||||||
|
/usr/local/include/php/TSRM/TSRM.h \
|
||||||
|
/usr/local/include/php/Zend/zend_constants.h \
|
||||||
|
/usr/local/include/php/main/php_reentrancy.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/php_sdl3.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_events.h
|
||||||
26
php-sdl3/sdl3_events.h
Normal file
26
php-sdl3/sdl3_events.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef PHP_SDL3_EVENTS_H
|
||||||
|
#define PHP_SDL3_EVENTS_H
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
// PHP Funktionen für SDL3 Events
|
||||||
|
PHP_FUNCTION(sdl_poll_event);
|
||||||
|
PHP_FUNCTION(sdl_wait_event);
|
||||||
|
PHP_FUNCTION(sdl_wait_event_timeout);
|
||||||
|
|
||||||
|
// Argument Info
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_poll_event, 0, 0, 0)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_wait_event, 0, 0, 0)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_wait_event_timeout, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, timeout_ms)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
// Funktion zum Registrieren von Event-Konstanten
|
||||||
|
void sdl3_events_register_constants(int module_number);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
php-sdl3/sdl3_events.lo
Normal file
12
php-sdl3/sdl3_events.lo
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# sdl3_events.lo - a libtool object file
|
||||||
|
# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.492 2008/01/30 06:40:56)
|
||||||
|
#
|
||||||
|
# Please DO NOT delete this file!
|
||||||
|
# It is necessary for linking the library.
|
||||||
|
|
||||||
|
# Name of the PIC object.
|
||||||
|
pic_object='.libs/sdl3_events.o'
|
||||||
|
|
||||||
|
# Name of the non-PIC object.
|
||||||
|
non_pic_object=none
|
||||||
|
|
||||||
66
php-sdl3/sdl3_image.c
Normal file
66
php-sdl3/sdl3_image.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "php_sdl3.h"
|
||||||
|
#include "sdl3_image.h"
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3_image/SDL_image.h>
|
||||||
|
|
||||||
|
// Resource handles
|
||||||
|
int le_sdl_surface;
|
||||||
|
|
||||||
|
// Destructor für Surface
|
||||||
|
void sdl_surface_dtor(zend_resource *rsrc) {
|
||||||
|
SDL_Surface *surface = (SDL_Surface *)rsrc->ptr;
|
||||||
|
if (surface) {
|
||||||
|
SDL_DestroySurface(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registriert die Resource-Typen
|
||||||
|
void sdl3_image_register_resources(int module_number) {
|
||||||
|
le_sdl_surface = zend_register_list_destructors_ex(sdl_surface_dtor, NULL, "SDL_Surface", module_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(img_load) {
|
||||||
|
char *file;
|
||||||
|
size_t file_len;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &file, &file_len) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface *surface = IMG_Load(file);
|
||||||
|
if (!surface) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Failed to load image: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_RES(zend_register_resource(surface, le_sdl_surface));
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(img_load_texture) {
|
||||||
|
zval *ren_res;
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
char *file;
|
||||||
|
size_t file_len;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &ren_res, &file, &file_len) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer = (SDL_Renderer *)zend_fetch_resource(Z_RES_P(ren_res), "SDL_Renderer", le_sdl_renderer);
|
||||||
|
if (!renderer) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Texture *texture = IMG_LoadTexture(renderer, file);
|
||||||
|
if (!texture) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Failed to load texture: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_RES(zend_register_resource(texture, le_sdl_texture));
|
||||||
|
}
|
||||||
95
php-sdl3/sdl3_image.dep
Normal file
95
php-sdl3/sdl3_image.dep
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
sdl3_image.lo: \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_image.c \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/config.h \
|
||||||
|
/usr/local/include/php/main/php.h \
|
||||||
|
/usr/local/include/php/main/php_version.h \
|
||||||
|
/usr/local/include/php/Zend/zend.h \
|
||||||
|
/usr/local/include/php/Zend/zend_types.h \
|
||||||
|
/usr/local/include/php/Zend/zend_portability.h \
|
||||||
|
/usr/local/include/php/Zend/zend_config.h \
|
||||||
|
/usr/local/include/php/main/../main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/../TSRM/TSRM.h \
|
||||||
|
/usr/local/include/php/main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/zend_range_check.h \
|
||||||
|
/usr/local/include/php/Zend/zend_long.h \
|
||||||
|
/usr/local/include/php/Zend/zend_map_ptr.h \
|
||||||
|
/usr/local/include/php/Zend/zend_errors.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc_sizes.h \
|
||||||
|
/usr/local/include/php/Zend/zend_llist.h \
|
||||||
|
/usr/local/include/php/Zend/zend_string.h \
|
||||||
|
/usr/local/include/php/Zend/zend_gc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hrtime.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hash.h \
|
||||||
|
/usr/local/include/php/Zend/zend_sort.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ast.h \
|
||||||
|
/usr/local/include/php/Zend/zend_variables.h \
|
||||||
|
/usr/local/include/php/Zend/zend_iterators.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stream.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_str_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_string_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_signal.h \
|
||||||
|
/usr/local/include/php/Zend/zend_max_execution_timer.h \
|
||||||
|
/usr/local/include/php/Zend/zend_object_handlers.h \
|
||||||
|
/usr/local/include/php/Zend/zend_property_hooks.h \
|
||||||
|
/usr/local/include/php/Zend/zend_lazy_objects.h \
|
||||||
|
/usr/local/include/php/Zend/zend_types.h \
|
||||||
|
/usr/local/include/php/Zend/zend_operators.h \
|
||||||
|
/usr/local/include/php/Zend/zend_strtod.h \
|
||||||
|
/usr/local/include/php/Zend/zend_multiply.h \
|
||||||
|
/usr/local/include/php/Zend/zend_sort.h \
|
||||||
|
/usr/local/include/php/main/php_compat.h \
|
||||||
|
/usr/local/include/php/main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/zend_API.h \
|
||||||
|
/usr/local/include/php/Zend/zend_modules.h \
|
||||||
|
/usr/local/include/php/Zend/zend.h \
|
||||||
|
/usr/local/include/php/Zend/zend_compile.h \
|
||||||
|
/usr/local/include/php/Zend/zend_frameless_function.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals_macros.h \
|
||||||
|
/usr/local/include/php/Zend/zend_atomic.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ptr_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_objects.h \
|
||||||
|
/usr/local/include/php/Zend/zend_objects_API.h \
|
||||||
|
/usr/local/include/php/Zend/zend_float.h \
|
||||||
|
/usr/local/include/php/Zend/zend_multibyte.h \
|
||||||
|
/usr/local/include/php/Zend/zend_arena.h \
|
||||||
|
/usr/local/include/php/Zend/zend_call_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_vm_opcodes.h \
|
||||||
|
/usr/local/include/php/Zend/zend_build.h \
|
||||||
|
/usr/local/include/php/Zend/zend_list.h \
|
||||||
|
/usr/local/include/php/Zend/zend_execute.h \
|
||||||
|
/usr/local/include/php/Zend/zend_type_info.h \
|
||||||
|
/usr/local/include/php/main/build-defs.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hash.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stack.h \
|
||||||
|
/usr/local/include/php/main/snprintf.h \
|
||||||
|
/usr/local/include/php/main/spprintf.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_str_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_string_public.h \
|
||||||
|
/usr/local/include/php/main/php_syslog.h \
|
||||||
|
/usr/local/include/php/main/php.h \
|
||||||
|
/usr/local/include/php/main/php_output.h \
|
||||||
|
/usr/local/include/php/main/php_streams.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stream.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_context.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_filter_api.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_transport.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_plain_wrapper.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_glob_wrapper.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_userspace.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_mmap.h \
|
||||||
|
/usr/local/include/php/main/php_memory_streams.h \
|
||||||
|
/usr/local/include/php/main/fopen_wrappers.h \
|
||||||
|
/usr/local/include/php/main/php_globals.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals.h \
|
||||||
|
/usr/local/include/php/main/php_ini.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ini.h \
|
||||||
|
/usr/local/include/php/Zend/zend_virtual_cwd.h \
|
||||||
|
/usr/local/include/php/TSRM/TSRM.h \
|
||||||
|
/usr/local/include/php/Zend/zend_constants.h \
|
||||||
|
/usr/local/include/php/main/php_reentrancy.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/php_sdl3.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_image.h
|
||||||
31
php-sdl3/sdl3_image.h
Normal file
31
php-sdl3/sdl3_image.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef PHP_SDL3_IMAGE_H
|
||||||
|
#define PHP_SDL3_IMAGE_H
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3_image/SDL_image.h>
|
||||||
|
|
||||||
|
// Resource handle für SDL_Surface
|
||||||
|
extern int le_sdl_surface;
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
void sdl_surface_dtor(zend_resource *rsrc);
|
||||||
|
|
||||||
|
// PHP Funktionen für SDL3_image
|
||||||
|
PHP_FUNCTION(img_load);
|
||||||
|
PHP_FUNCTION(img_load_texture);
|
||||||
|
|
||||||
|
// Argument Info
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_img_load, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, file)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_img_load_texture, 0, 0, 2)
|
||||||
|
ZEND_ARG_INFO(0, renderer)
|
||||||
|
ZEND_ARG_INFO(0, file)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
// Funktion zum Registrieren der Resource-Typen
|
||||||
|
void sdl3_image_register_resources(int module_number);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
php-sdl3/sdl3_image.lo
Normal file
12
php-sdl3/sdl3_image.lo
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# sdl3_image.lo - a libtool object file
|
||||||
|
# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.492 2008/01/30 06:40:56)
|
||||||
|
#
|
||||||
|
# Please DO NOT delete this file!
|
||||||
|
# It is necessary for linking the library.
|
||||||
|
|
||||||
|
# Name of the PIC object.
|
||||||
|
pic_object='.libs/sdl3_image.o'
|
||||||
|
|
||||||
|
# Name of the non-PIC object.
|
||||||
|
non_pic_object=none
|
||||||
|
|
||||||
170
php-sdl3/sdl3_ttf.c
Normal file
170
php-sdl3/sdl3_ttf.c
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "php_sdl3.h"
|
||||||
|
#include "sdl3_ttf.h"
|
||||||
|
#include "sdl3_image.h"
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3_ttf/SDL_ttf.h>
|
||||||
|
|
||||||
|
// Resource handles
|
||||||
|
int le_ttf_font;
|
||||||
|
|
||||||
|
// Destructor für Font
|
||||||
|
void ttf_font_dtor(zend_resource *rsrc) {
|
||||||
|
TTF_Font *font = (TTF_Font *)rsrc->ptr;
|
||||||
|
if (font) {
|
||||||
|
TTF_CloseFont(font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registriert die Resource-Typen
|
||||||
|
void sdl3_ttf_register_resources(int module_number) {
|
||||||
|
le_ttf_font = zend_register_list_destructors_ex(ttf_font_dtor, NULL, "TTF_Font", module_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(ttf_init) {
|
||||||
|
if (!TTF_Init()) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "TTF_Init failed: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(ttf_open_font) {
|
||||||
|
char *file;
|
||||||
|
size_t file_len;
|
||||||
|
zend_long ptsize;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &file, &file_len, &ptsize) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
TTF_Font *font = TTF_OpenFont(file, (float)ptsize);
|
||||||
|
if (!font) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Failed to open font: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_RES(zend_register_resource(font, le_ttf_font));
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(ttf_close_font) {
|
||||||
|
zval *font_res;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &font_res) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resource wird automatisch durch den Destructor freigegeben
|
||||||
|
zend_list_close(Z_RES_P(font_res));
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(ttf_render_text_solid) {
|
||||||
|
zval *font_res;
|
||||||
|
TTF_Font *font;
|
||||||
|
char *text;
|
||||||
|
size_t text_len;
|
||||||
|
zend_long r, g, b;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rslll", &font_res, &text, &text_len, &r, &g, &b) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
font = (TTF_Font *)zend_fetch_resource(Z_RES_P(font_res), "TTF_Font", le_ttf_font);
|
||||||
|
if (!font) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Color color = {(Uint8)r, (Uint8)g, (Uint8)b, 255};
|
||||||
|
SDL_Surface *surface = TTF_RenderText_Solid(font, text, text_len, color);
|
||||||
|
if (!surface) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Failed to render text: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_RES(zend_register_resource(surface, le_sdl_surface));
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(ttf_render_text_blended) {
|
||||||
|
zval *font_res;
|
||||||
|
TTF_Font *font;
|
||||||
|
char *text;
|
||||||
|
size_t text_len;
|
||||||
|
zend_long r, g, b;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rslll", &font_res, &text, &text_len, &r, &g, &b) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
font = (TTF_Font *)zend_fetch_resource(Z_RES_P(font_res), "TTF_Font", le_ttf_font);
|
||||||
|
if (!font) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Color color = {(Uint8)r, (Uint8)g, (Uint8)b, 255};
|
||||||
|
SDL_Surface *surface = TTF_RenderText_Blended(font, text, text_len, color);
|
||||||
|
if (!surface) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Failed to render text: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_RES(zend_register_resource(surface, le_sdl_surface));
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(ttf_render_text_shaded) {
|
||||||
|
zval *font_res;
|
||||||
|
TTF_Font *font;
|
||||||
|
char *text;
|
||||||
|
size_t text_len;
|
||||||
|
zend_long fg_r, fg_g, fg_b, bg_r, bg_g, bg_b;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsllllll", &font_res, &text, &text_len,
|
||||||
|
&fg_r, &fg_g, &fg_b, &bg_r, &bg_g, &bg_b) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
font = (TTF_Font *)zend_fetch_resource(Z_RES_P(font_res), "TTF_Font", le_ttf_font);
|
||||||
|
if (!font) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Color fg_color = {(Uint8)fg_r, (Uint8)fg_g, (Uint8)fg_b, 255};
|
||||||
|
SDL_Color bg_color = {(Uint8)bg_r, (Uint8)bg_g, (Uint8)bg_b, 255};
|
||||||
|
SDL_Surface *surface = TTF_RenderText_Shaded(font, text, text_len, fg_color, bg_color);
|
||||||
|
if (!surface) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Failed to render text: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_RES(zend_register_resource(surface, le_sdl_surface));
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_FUNCTION(ttf_size_text) {
|
||||||
|
zval *font_res;
|
||||||
|
TTF_Font *font;
|
||||||
|
char *text;
|
||||||
|
size_t text_len;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &font_res, &text, &text_len) == FAILURE) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
font = (TTF_Font *)zend_fetch_resource(Z_RES_P(font_res), "TTF_Font", le_ttf_font);
|
||||||
|
if (!font) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
if (!TTF_GetStringSize(font, text, text_len, &w, &h)) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Failed to get text size: %s", SDL_GetError());
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_init(return_value);
|
||||||
|
add_assoc_long(return_value, "w", w);
|
||||||
|
add_assoc_long(return_value, "h", h);
|
||||||
|
}
|
||||||
96
php-sdl3/sdl3_ttf.dep
Normal file
96
php-sdl3/sdl3_ttf.dep
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
sdl3_ttf.lo: \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_ttf.c \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/config.h \
|
||||||
|
/usr/local/include/php/main/php.h \
|
||||||
|
/usr/local/include/php/main/php_version.h \
|
||||||
|
/usr/local/include/php/Zend/zend.h \
|
||||||
|
/usr/local/include/php/Zend/zend_types.h \
|
||||||
|
/usr/local/include/php/Zend/zend_portability.h \
|
||||||
|
/usr/local/include/php/Zend/zend_config.h \
|
||||||
|
/usr/local/include/php/main/../main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/../TSRM/TSRM.h \
|
||||||
|
/usr/local/include/php/main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/zend_range_check.h \
|
||||||
|
/usr/local/include/php/Zend/zend_long.h \
|
||||||
|
/usr/local/include/php/Zend/zend_map_ptr.h \
|
||||||
|
/usr/local/include/php/Zend/zend_errors.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc_sizes.h \
|
||||||
|
/usr/local/include/php/Zend/zend_llist.h \
|
||||||
|
/usr/local/include/php/Zend/zend_string.h \
|
||||||
|
/usr/local/include/php/Zend/zend_gc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hrtime.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hash.h \
|
||||||
|
/usr/local/include/php/Zend/zend_sort.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ast.h \
|
||||||
|
/usr/local/include/php/Zend/zend_variables.h \
|
||||||
|
/usr/local/include/php/Zend/zend_iterators.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stream.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_str_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_string_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_signal.h \
|
||||||
|
/usr/local/include/php/Zend/zend_max_execution_timer.h \
|
||||||
|
/usr/local/include/php/Zend/zend_object_handlers.h \
|
||||||
|
/usr/local/include/php/Zend/zend_property_hooks.h \
|
||||||
|
/usr/local/include/php/Zend/zend_lazy_objects.h \
|
||||||
|
/usr/local/include/php/Zend/zend_types.h \
|
||||||
|
/usr/local/include/php/Zend/zend_operators.h \
|
||||||
|
/usr/local/include/php/Zend/zend_strtod.h \
|
||||||
|
/usr/local/include/php/Zend/zend_multiply.h \
|
||||||
|
/usr/local/include/php/Zend/zend_sort.h \
|
||||||
|
/usr/local/include/php/main/php_compat.h \
|
||||||
|
/usr/local/include/php/main/php_config.h \
|
||||||
|
/usr/local/include/php/Zend/zend_API.h \
|
||||||
|
/usr/local/include/php/Zend/zend_modules.h \
|
||||||
|
/usr/local/include/php/Zend/zend.h \
|
||||||
|
/usr/local/include/php/Zend/zend_compile.h \
|
||||||
|
/usr/local/include/php/Zend/zend_frameless_function.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals_macros.h \
|
||||||
|
/usr/local/include/php/Zend/zend_atomic.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ptr_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_objects.h \
|
||||||
|
/usr/local/include/php/Zend/zend_objects_API.h \
|
||||||
|
/usr/local/include/php/Zend/zend_float.h \
|
||||||
|
/usr/local/include/php/Zend/zend_multibyte.h \
|
||||||
|
/usr/local/include/php/Zend/zend_arena.h \
|
||||||
|
/usr/local/include/php/Zend/zend_call_stack.h \
|
||||||
|
/usr/local/include/php/Zend/zend_vm_opcodes.h \
|
||||||
|
/usr/local/include/php/Zend/zend_build.h \
|
||||||
|
/usr/local/include/php/Zend/zend_list.h \
|
||||||
|
/usr/local/include/php/Zend/zend_execute.h \
|
||||||
|
/usr/local/include/php/Zend/zend_type_info.h \
|
||||||
|
/usr/local/include/php/main/build-defs.h \
|
||||||
|
/usr/local/include/php/Zend/zend_hash.h \
|
||||||
|
/usr/local/include/php/Zend/zend_alloc.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stack.h \
|
||||||
|
/usr/local/include/php/main/snprintf.h \
|
||||||
|
/usr/local/include/php/main/spprintf.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_str_public.h \
|
||||||
|
/usr/local/include/php/Zend/zend_smart_string_public.h \
|
||||||
|
/usr/local/include/php/main/php_syslog.h \
|
||||||
|
/usr/local/include/php/main/php.h \
|
||||||
|
/usr/local/include/php/main/php_output.h \
|
||||||
|
/usr/local/include/php/main/php_streams.h \
|
||||||
|
/usr/local/include/php/Zend/zend_stream.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_context.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_filter_api.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_transport.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_plain_wrapper.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_glob_wrapper.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_userspace.h \
|
||||||
|
/usr/local/include/php/main/streams/php_stream_mmap.h \
|
||||||
|
/usr/local/include/php/main/php_memory_streams.h \
|
||||||
|
/usr/local/include/php/main/fopen_wrappers.h \
|
||||||
|
/usr/local/include/php/main/php_globals.h \
|
||||||
|
/usr/local/include/php/Zend/zend_globals.h \
|
||||||
|
/usr/local/include/php/main/php_ini.h \
|
||||||
|
/usr/local/include/php/Zend/zend_ini.h \
|
||||||
|
/usr/local/include/php/Zend/zend_virtual_cwd.h \
|
||||||
|
/usr/local/include/php/TSRM/TSRM.h \
|
||||||
|
/usr/local/include/php/Zend/zend_constants.h \
|
||||||
|
/usr/local/include/php/main/php_reentrancy.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/php_sdl3.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_ttf.h \
|
||||||
|
/home/thomas/projekte/phpnative/framework/php-sdl3/sdl3_image.h
|
||||||
71
php-sdl3/sdl3_ttf.h
Normal file
71
php-sdl3/sdl3_ttf.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#ifndef PHP_SDL3_TTF_H
|
||||||
|
#define PHP_SDL3_TTF_H
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3_ttf/SDL_ttf.h>
|
||||||
|
|
||||||
|
// Resource handle für TTF_Font
|
||||||
|
extern int le_ttf_font;
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
void ttf_font_dtor(zend_resource *rsrc);
|
||||||
|
|
||||||
|
// PHP Funktionen für SDL3_ttf
|
||||||
|
PHP_FUNCTION(ttf_init);
|
||||||
|
PHP_FUNCTION(ttf_open_font);
|
||||||
|
PHP_FUNCTION(ttf_close_font);
|
||||||
|
PHP_FUNCTION(ttf_render_text_solid);
|
||||||
|
PHP_FUNCTION(ttf_render_text_blended);
|
||||||
|
PHP_FUNCTION(ttf_render_text_shaded);
|
||||||
|
PHP_FUNCTION(ttf_size_text);
|
||||||
|
|
||||||
|
// Argument Info
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_ttf_init, 0, 0, 0)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_ttf_open_font, 0, 0, 2)
|
||||||
|
ZEND_ARG_INFO(0, file)
|
||||||
|
ZEND_ARG_INFO(0, ptsize)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_ttf_close_font, 0, 0, 1)
|
||||||
|
ZEND_ARG_INFO(0, font)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_ttf_render_text_solid, 0, 0, 5)
|
||||||
|
ZEND_ARG_INFO(0, font)
|
||||||
|
ZEND_ARG_INFO(0, text)
|
||||||
|
ZEND_ARG_INFO(0, r)
|
||||||
|
ZEND_ARG_INFO(0, g)
|
||||||
|
ZEND_ARG_INFO(0, b)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_ttf_render_text_blended, 0, 0, 5)
|
||||||
|
ZEND_ARG_INFO(0, font)
|
||||||
|
ZEND_ARG_INFO(0, text)
|
||||||
|
ZEND_ARG_INFO(0, r)
|
||||||
|
ZEND_ARG_INFO(0, g)
|
||||||
|
ZEND_ARG_INFO(0, b)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_ttf_render_text_shaded, 0, 0, 8)
|
||||||
|
ZEND_ARG_INFO(0, font)
|
||||||
|
ZEND_ARG_INFO(0, text)
|
||||||
|
ZEND_ARG_INFO(0, fg_r)
|
||||||
|
ZEND_ARG_INFO(0, fg_g)
|
||||||
|
ZEND_ARG_INFO(0, fg_b)
|
||||||
|
ZEND_ARG_INFO(0, bg_r)
|
||||||
|
ZEND_ARG_INFO(0, bg_g)
|
||||||
|
ZEND_ARG_INFO(0, bg_b)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_ttf_size_text, 0, 0, 2)
|
||||||
|
ZEND_ARG_INFO(0, font)
|
||||||
|
ZEND_ARG_INFO(0, text)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
// Funktion zum Registrieren der Resource-Typen
|
||||||
|
void sdl3_ttf_register_resources(int module_number);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
php-sdl3/sdl3_ttf.lo
Normal file
12
php-sdl3/sdl3_ttf.lo
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# sdl3_ttf.lo - a libtool object file
|
||||||
|
# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.492 2008/01/30 06:40:56)
|
||||||
|
#
|
||||||
|
# Please DO NOT delete this file!
|
||||||
|
# It is necessary for linking the library.
|
||||||
|
|
||||||
|
# Name of the PIC object.
|
||||||
|
pic_object='.libs/sdl3_ttf.o'
|
||||||
|
|
||||||
|
# Name of the non-PIC object.
|
||||||
|
non_pic_object=none
|
||||||
|
|
||||||
35
php-sdl3/test_functions.php
Normal file
35
php-sdl3/test_functions.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!extension_loaded('sdl3')) {
|
||||||
|
echo "Die Erweiterung 'sdl3' ist nicht geladen.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "SDL3 Extension erfolgreich geladen!\n\n";
|
||||||
|
|
||||||
|
echo "Verfügbare Funktionen:\n";
|
||||||
|
echo "======================\n\n";
|
||||||
|
|
||||||
|
echo "SDL3 Core:\n";
|
||||||
|
$core_functions = ['sdl_init', 'sdl_quit', 'sdl_create_window', 'sdl_create_renderer',
|
||||||
|
'sdl_set_render_draw_color', 'sdl_render_clear', 'sdl_render_fill_rect',
|
||||||
|
'sdl_render_present', 'sdl_delay', 'sdl_get_error', 'sdl_rounded_box',
|
||||||
|
'sdl_rounded_box_ex'];
|
||||||
|
foreach ($core_functions as $func) {
|
||||||
|
echo " - $func: " . (function_exists($func) ? "✓" : "✗") . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\nSDL3_image:\n";
|
||||||
|
$image_functions = ['img_load', 'img_load_texture'];
|
||||||
|
foreach ($image_functions as $func) {
|
||||||
|
echo " - $func: " . (function_exists($func) ? "✓" : "✗") . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\nSDL3_ttf:\n";
|
||||||
|
$ttf_functions = ['ttf_init', 'ttf_open_font', 'ttf_close_font', 'ttf_render_text_solid',
|
||||||
|
'ttf_render_text_blended', 'ttf_render_text_shaded', 'ttf_size_text'];
|
||||||
|
foreach ($ttf_functions as $func) {
|
||||||
|
echo " - $func: " . (function_exists($func) ? "✓" : "✗") . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\nAlle Funktionen wurden erfolgreich registriert!\n";
|
||||||
@ -12,12 +12,13 @@ class Application
|
|||||||
protected array $windows = [];
|
protected array $windows = [];
|
||||||
protected int $nextWindowId = 0;
|
protected int $nextWindowId = 0;
|
||||||
protected bool $running = true;
|
protected bool $running = true;
|
||||||
|
protected array $closedWindowIds = []; // Track recently closed window IDs
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
self::$instance = $this;
|
self::$instance = $this;
|
||||||
|
|
||||||
rgfw_setQueueEvents(true);
|
// SDL3 uses event queue by default, no need to enable it
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,6 +48,18 @@ class Application
|
|||||||
return $window;
|
return $window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an existing window to the application
|
||||||
|
*
|
||||||
|
* @param Window $window The window to add
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addWindow(Window $window): void
|
||||||
|
{
|
||||||
|
$windowId = $this->nextWindowId++;
|
||||||
|
$this->windows[$windowId] = $window;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all windows
|
* Get all windows
|
||||||
*/
|
*/
|
||||||
@ -75,12 +88,52 @@ class Application
|
|||||||
echo 'Layoutout: ' . PHP_EOL;
|
echo 'Layoutout: ' . PHP_EOL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Poll events globally for all windows (event queue mode, if available)
|
// SDL3: Poll all events globally and distribute to the correct windows
|
||||||
rgfw_pollEvents();
|
$events = [];
|
||||||
|
while ($event = sdl_poll_event()) {
|
||||||
|
$events[] = $event;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle events for all windows (now that layout is done)
|
// Distribute events to windows based on window_id
|
||||||
|
foreach ($events as $event) {
|
||||||
|
$eventWindowId = $event['window_id'] ?? null;
|
||||||
|
|
||||||
|
// Debug event distribution
|
||||||
|
if (defined('DEBUG_EVENTS') && DEBUG_EVENTS && $eventWindowId !== null) {
|
||||||
|
$eventType = $event['type'];
|
||||||
|
error_log("[Application] Distributing event type={$eventType} to window_id={$eventWindowId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global events (like QUIT) go to all windows
|
||||||
|
if ($eventWindowId === null) {
|
||||||
foreach ($this->windows as $windowId => $window) {
|
foreach ($this->windows as $windowId => $window) {
|
||||||
$window->handleEvents();
|
$window->processEvent($event);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Window-specific events go to the correct window
|
||||||
|
$delivered = false;
|
||||||
|
foreach ($this->windows as $windowId => $window) {
|
||||||
|
if ($window->getWindowId() === $eventWindowId) {
|
||||||
|
$window->processEvent($event);
|
||||||
|
$delivered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$delivered) {
|
||||||
|
// Check if this is a recently closed window (expected)
|
||||||
|
if (!in_array($eventWindowId, $this->closedWindowIds)) {
|
||||||
|
if (defined('DEBUG_EVENTS') && DEBUG_EVENTS) {
|
||||||
|
error_log("[Application] WARNING: Event for window_id={$eventWindowId} could not be delivered (window not found)");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This is a recently closed window, events are expected
|
||||||
|
if (defined('DEBUG_EVENTS') && DEBUG_EVENTS) {
|
||||||
|
error_log("[Application] Ignoring event for recently closed window_id={$eventWindowId}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update async tasks (global)
|
// Update async tasks (global)
|
||||||
@ -98,13 +151,25 @@ class Application
|
|||||||
// Remove closed windows
|
// Remove closed windows
|
||||||
foreach ($this->windows as $windowId => $window) {
|
foreach ($this->windows as $windowId => $window) {
|
||||||
if ($window->shouldClose()) {
|
if ($window->shouldClose()) {
|
||||||
$window->cleanup(); // Frees the TextRenderer to prevent "fat text" bug
|
// Track this window ID as recently closed
|
||||||
rgfw_window_close($window->getWindowResource()); // Now, safely close the native window
|
$sdlWindowId = $window->getWindowId();
|
||||||
|
if (!in_array($sdlWindowId, $this->closedWindowIds)) {
|
||||||
|
$this->closedWindowIds[] = $sdlWindowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explicitly destroy the window (closes SDL window, renderer, and text renderer)
|
||||||
|
$window->destroy();
|
||||||
unset($this->windows[$windowId]);
|
unset($this->windows[$windowId]);
|
||||||
$oneWindowIsClosed = true;
|
$oneWindowIsClosed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up old closed window IDs after 10 frames (to prevent memory leak)
|
||||||
|
// This gives SDL enough time to stop sending events for closed windows
|
||||||
|
if (count($this->closedWindowIds) > 10) {
|
||||||
|
array_shift($this->closedWindowIds);
|
||||||
|
}
|
||||||
|
|
||||||
if ($oneWindowIsClosed) {
|
if ($oneWindowIsClosed) {
|
||||||
foreach ($this->windows as $windowId => $window) {
|
foreach ($this->windows as $windowId => $window) {
|
||||||
$window->setShouldBeReLayouted(true);
|
$window->setShouldBeReLayouted(true);
|
||||||
|
|||||||
@ -8,28 +8,33 @@ namespace PHPNative\Framework;
|
|||||||
|
|
||||||
class TextRenderer
|
class TextRenderer
|
||||||
{
|
{
|
||||||
private $window;
|
private $renderer;
|
||||||
|
private $font = null;
|
||||||
private bool $initialized = false;
|
private bool $initialized = false;
|
||||||
private string $fontPath;
|
private string $fontPath;
|
||||||
private int $fontSize;
|
private int $fontSize;
|
||||||
|
private float $colorR = 1.0;
|
||||||
|
private float $colorG = 1.0;
|
||||||
|
private float $colorB = 1.0;
|
||||||
|
private float $colorA = 1.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param resource $window RGFW window resource
|
* @param resource $renderer SDL Renderer resource
|
||||||
*/
|
*/
|
||||||
public function __construct($window)
|
public function __construct($renderer)
|
||||||
{
|
{
|
||||||
$this->window = $window;
|
$this->renderer = $renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize RFont with a font file
|
* Initialize TTF with a font file
|
||||||
*
|
*
|
||||||
* @param string|null $fontPath Path to TTF font file
|
* @param string|null $fontPath Path to TTF font file
|
||||||
* @param int $fontSize Default font size
|
* @param int $fontSize Default font size
|
||||||
* @param int $atlasWidth Font atlas texture width (default 512)
|
* @param int $atlasWidth Font atlas texture width (ignored, for compatibility)
|
||||||
* @param int $atlasHeight Font atlas texture height (default 512)
|
* @param int $atlasHeight Font atlas texture height (ignored, for compatibility)
|
||||||
* @return bool Success
|
* @return bool Success
|
||||||
*/
|
*/
|
||||||
public function init(
|
public function init(
|
||||||
@ -51,13 +56,16 @@ class TextRenderer
|
|||||||
$this->fontPath = $fontPath;
|
$this->fontPath = $fontPath;
|
||||||
$this->fontSize = $fontSize;
|
$this->fontSize = $fontSize;
|
||||||
|
|
||||||
$this->initialized = rfont_init($this->window, $fontPath, $fontSize, $atlasWidth, $atlasHeight);
|
$this->font = ttf_open_font($fontPath, $fontSize);
|
||||||
|
|
||||||
if (!$this->initialized) {
|
if (!$this->font) {
|
||||||
error_log("Failed to initialize RFont with font: {$fontPath}");
|
error_log("Failed to open font: {$fontPath}");
|
||||||
|
$this->initialized = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->initialized = true;
|
||||||
|
|
||||||
// Set default color to white
|
// Set default color to white
|
||||||
$this->setColor(1.0, 1.0, 1.0, 1.0);
|
$this->setColor(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
@ -103,15 +111,43 @@ class TextRenderer
|
|||||||
*/
|
*/
|
||||||
public function drawText(string $text, int $x, int $y, null|int $size = null): void
|
public function drawText(string $text, int $x, int $y, null|int $size = null): void
|
||||||
{
|
{
|
||||||
if (!$this->initialized) {
|
if (!$this->initialized || !$this->font) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($size === null) {
|
// SDL_ttf doesn't support variable font sizes easily
|
||||||
$size = $this->fontSize;
|
// We use the font size that was set when the font was opened
|
||||||
|
// For different sizes, you'd need to open multiple font instances
|
||||||
|
|
||||||
|
// Convert float color (0.0-1.0) to int (0-255)
|
||||||
|
$r = (int) ($this->colorR * 255);
|
||||||
|
$g = (int) ($this->colorG * 255);
|
||||||
|
$b = (int) ($this->colorB * 255);
|
||||||
|
|
||||||
|
// Render text to surface with anti-aliasing (blended mode for smooth text)
|
||||||
|
$surface = ttf_render_text_blended($this->font, $text, $r, $g, $b);
|
||||||
|
if (!$surface) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfont_drawText($this->window, $text, $x, $y, $size);
|
// Create texture from surface
|
||||||
|
$texture = sdl_create_texture_from_surface($this->renderer, $surface);
|
||||||
|
if (!$texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get text size
|
||||||
|
$textSize = ttf_size_text($this->font, $text);
|
||||||
|
|
||||||
|
// Render texture
|
||||||
|
sdl_render_texture($this->renderer, $texture, [
|
||||||
|
'x' => $x,
|
||||||
|
'y' => $y,
|
||||||
|
'w' => $textSize['w'],
|
||||||
|
'h' => $textSize['h']
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Note: Texture and surface are automatically cleaned up by PHP resource destructors
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,11 +160,10 @@ class TextRenderer
|
|||||||
*/
|
*/
|
||||||
public function setColor(float $r, float $g, float $b, float $a = 1.0): void
|
public function setColor(float $r, float $g, float $b, float $a = 1.0): void
|
||||||
{
|
{
|
||||||
if (!$this->initialized) {
|
$this->colorR = $r;
|
||||||
return;
|
$this->colorG = $g;
|
||||||
}
|
$this->colorB = $b;
|
||||||
|
$this->colorA = $a;
|
||||||
rfont_setColor($this->window, $r, $g, $b, $a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,24 +175,13 @@ class TextRenderer
|
|||||||
*/
|
*/
|
||||||
public function measureText(string $text, null|int $size = null): array
|
public function measureText(string $text, null|int $size = null): array
|
||||||
{
|
{
|
||||||
if (!$this->initialized) {
|
if (!$this->initialized || !$this->font) {
|
||||||
return [0, 0];
|
return [0, 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($size === null) {
|
// Get text size using TTF
|
||||||
$size = $this->fontSize;
|
$dimensions = ttf_size_text($this->font, $text);
|
||||||
}
|
return [(int) $dimensions['w'], (int) $dimensions['h']];
|
||||||
|
|
||||||
// Try to use rfont_getTextSize if available, otherwise estimate
|
|
||||||
if (function_exists('rfont_getTextSize')) {
|
|
||||||
$dimensions = rfont_getTextSize($this->window, $text, $size);
|
|
||||||
return [(int) $dimensions[0], (int) $dimensions[1]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: estimate based on font size
|
|
||||||
$width = strlen($text) * ($size * 0.6); // Rough estimate
|
|
||||||
$height = $size * 1.2; // Line height
|
|
||||||
return [(int) $width, (int) $height];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,20 +192,18 @@ class TextRenderer
|
|||||||
*/
|
*/
|
||||||
public function updateFramebuffer(int $width, int $height): void
|
public function updateFramebuffer(int $width, int $height): void
|
||||||
{
|
{
|
||||||
if (!$this->initialized) {
|
// SDL3 handles this automatically through the renderer
|
||||||
return;
|
// This method is kept for compatibility but does nothing
|
||||||
}
|
|
||||||
|
|
||||||
rfont_setFramebuffer($this->window, $width, $height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free RFont resources
|
* Free TTF resources
|
||||||
*/
|
*/
|
||||||
public function free(): void
|
public function free(): void
|
||||||
{
|
{
|
||||||
if ($this->initialized) {
|
if ($this->initialized && $this->font) {
|
||||||
rfont_free($this->window);
|
ttf_close_font($this->font);
|
||||||
|
$this->font = null;
|
||||||
$this->initialized = false;
|
$this->initialized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,10 @@ class Flex implements Parser
|
|||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
return new \PHPNative\Tailwind\Style\Flex(type:FlexTypeEnum::none);
|
return new \PHPNative\Tailwind\Style\Flex(type:FlexTypeEnum::none);
|
||||||
}
|
}
|
||||||
|
preg_match_all('/flex-grow/', $style, $output_array);
|
||||||
|
if (count($output_array[0]) > 0) {
|
||||||
|
return new \PHPNative\Tailwind\Style\Flex(type:FlexTypeEnum::grow);
|
||||||
|
}
|
||||||
preg_match_all('/flex-1/', $style, $output_array);
|
preg_match_all('/flex-1/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
return new \PHPNative\Tailwind\Style\Flex(type:FlexTypeEnum::one);
|
return new \PHPNative\Tailwind\Style\Flex(type:FlexTypeEnum::one);
|
||||||
|
|||||||
@ -24,7 +24,8 @@ class Height implements Parser
|
|||||||
|
|
||||||
preg_match_all('/h-(\d*)/', $style, $output_array);
|
preg_match_all('/h-(\d*)/', $style, $output_array);
|
||||||
if (!$found && count($output_array[0]) > 0) {
|
if (!$found && count($output_array[0]) > 0) {
|
||||||
$value = (int)$output_array[1][0];
|
// Tailwind uses a 4px scale: h-1 = 4px, h-10 = 40px, etc.
|
||||||
|
$value = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/(h-full|h-screen)/', $style, $output_array);
|
preg_match_all('/(h-full|h-screen)/', $style, $output_array);
|
||||||
|
|||||||
@ -15,42 +15,42 @@ class Margin implements Parser
|
|||||||
|
|
||||||
preg_match_all('/m-(\d*)/', $style, $output_array);
|
preg_match_all('/m-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$l = (int)$output_array[1][0];
|
$l = (int)$output_array[1][0] * 4;
|
||||||
$r = (int)$output_array[1][0];
|
$r = (int)$output_array[1][0] * 4;
|
||||||
$t = (int)$output_array[1][0];
|
$t = (int)$output_array[1][0] * 4;
|
||||||
$b = (int)$output_array[1][0];
|
$b = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/mx-(\d*)/', $style, $output_array);
|
preg_match_all('/mx-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$l = (int)$output_array[1][0];
|
$l = (int)$output_array[1][0] * 4;
|
||||||
$r = (int)$output_array[1][0];
|
$r = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/my-(\d*)/', $style, $output_array);
|
preg_match_all('/my-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$t = (int)$output_array[1][0];
|
$t = (int)$output_array[1][0] * 4;
|
||||||
$b = (int)$output_array[1][0];
|
$b = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/mt-(\d*)/', $style, $output_array);
|
preg_match_all('/mt-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$t = (int)$output_array[1][0];
|
$t = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/mb-(\d*)/', $style, $output_array);
|
preg_match_all('/mb-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$b = (int)$output_array[1][0];
|
$b = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/ml-(\d*)/', $style, $output_array);
|
preg_match_all('/ml-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$l = (int)$output_array[1][0];
|
$l = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/mr-(\d*)/', $style, $output_array);
|
preg_match_all('/mr-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$r = (int)$output_array[1][0];
|
$r = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($l != null || $r != null || $t != null || $b != null) {
|
if($l != null || $r != null || $t != null || $b != null) {
|
||||||
|
|||||||
@ -15,42 +15,43 @@ class Padding implements Parser
|
|||||||
|
|
||||||
preg_match_all('/p-(\d*)/', $style, $output_array);
|
preg_match_all('/p-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$l = (int)$output_array[1][0];
|
// Tailwind uses a 4px scale
|
||||||
$r = (int)$output_array[1][0];
|
$l = (int)$output_array[1][0] * 4;
|
||||||
$t = (int)$output_array[1][0];
|
$r = (int)$output_array[1][0] * 4;
|
||||||
$b = (int)$output_array[1][0];
|
$t = (int)$output_array[1][0] * 4;
|
||||||
|
$b = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/px-(\d*)/', $style, $output_array);
|
preg_match_all('/px-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$l = (int)$output_array[1][0];
|
$l = (int)$output_array[1][0] * 4;
|
||||||
$r = (int)$output_array[1][0];
|
$r = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/py-(\d*)/', $style, $output_array);
|
preg_match_all('/py-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$t = (int)$output_array[1][0];
|
$t = (int)$output_array[1][0] * 4;
|
||||||
$b = (int)$output_array[1][0];
|
$b = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/pt-(\d*)/', $style, $output_array);
|
preg_match_all('/pt-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$t = (int)$output_array[1][0];
|
$t = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/pb-(\d*)/', $style, $output_array);
|
preg_match_all('/pb-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$b = (int)$output_array[1][0];
|
$b = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/pl-(\d*)/', $style, $output_array);
|
preg_match_all('/pl-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$l = (int)$output_array[1][0];
|
$l = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/pr-(\d*)/', $style, $output_array);
|
preg_match_all('/pr-(\d*)/', $style, $output_array);
|
||||||
if (count($output_array[0]) > 0) {
|
if (count($output_array[0]) > 0) {
|
||||||
$r = (int)$output_array[1][0];
|
$r = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($l != null || $r != null || $t != null || $b != null) {
|
if($l != null || $r != null || $t != null || $b != null) {
|
||||||
|
|||||||
@ -24,7 +24,8 @@ class Width implements Parser
|
|||||||
|
|
||||||
preg_match_all('/w-(\d*)/', $style, $output_array);
|
preg_match_all('/w-(\d*)/', $style, $output_array);
|
||||||
if (!$found && count($output_array[0]) > 0) {
|
if (!$found && count($output_array[0]) > 0) {
|
||||||
$value = (int)$output_array[1][0];
|
// Tailwind uses a 4px scale: w-1 = 4px, w-10 = 40px, etc.
|
||||||
|
$value = (int)$output_array[1][0] * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
preg_match_all('/(w-screen|w-full)/', $style, $output_array);
|
preg_match_all('/(w-screen|w-full)/', $style, $output_array);
|
||||||
|
|||||||
@ -9,4 +9,5 @@ enum FlexTypeEnum
|
|||||||
case auto;
|
case auto;
|
||||||
case initial;
|
case initial;
|
||||||
case one;
|
case one;
|
||||||
|
case grow;
|
||||||
}
|
}
|
||||||
@ -27,7 +27,19 @@ abstract class Component
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected string $style = '',
|
protected string $style = '',
|
||||||
) {}
|
) {
|
||||||
|
// Initialize viewports with default values
|
||||||
|
// These will be properly set during layout()
|
||||||
|
$this->viewport = new Viewport(
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
windowWidth: 800,
|
||||||
|
windowHeight: 600
|
||||||
|
);
|
||||||
|
$this->contentViewport = clone $this->viewport;
|
||||||
|
}
|
||||||
|
|
||||||
public function setViewport(Viewport $viewport): void
|
public function setViewport(Viewport $viewport): void
|
||||||
{
|
{
|
||||||
@ -101,7 +113,7 @@ abstract class Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(&$window, null|TextRenderer $textRenderer = null): void
|
public function render(&$renderer, null|TextRenderer $textRenderer = null): void
|
||||||
{
|
{
|
||||||
if (!$this->visible) {
|
if (!$this->visible) {
|
||||||
return;
|
return;
|
||||||
@ -112,43 +124,49 @@ abstract class Component
|
|||||||
($bg = $this->computedStyles[\PHPNative\Tailwind\Style\Background::class])
|
($bg = $this->computedStyles[\PHPNative\Tailwind\Style\Background::class])
|
||||||
) {
|
) {
|
||||||
if ($this->currentState == StateEnum::hover) {
|
if ($this->currentState == StateEnum::hover) {
|
||||||
rsgl_setColor($window, $bg->color->red, $bg->color->green, $bg->color->blue, 10);
|
sdl_set_render_draw_color($renderer, $bg->color->red, $bg->color->green, $bg->color->blue, 10);
|
||||||
} else {
|
} else {
|
||||||
rsgl_setColor($window, $bg->color->red, $bg->color->green, $bg->color->blue, $bg->color->alpha);
|
sdl_set_render_draw_color($renderer, $bg->color->red, $bg->color->green, $bg->color->blue, $bg->color->alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isset($this->computedStyles[\PHPNative\Tailwind\Style\Border::class]) &&
|
isset($this->computedStyles[\PHPNative\Tailwind\Style\Border::class]) &&
|
||||||
($border = $this->computedStyles[\PHPNative\Tailwind\Style\Border::class])
|
($border = $this->computedStyles[\PHPNative\Tailwind\Style\Border::class])
|
||||||
) {
|
) {
|
||||||
rsgl_drawRoundRectExF(
|
// SDL3: sdl_rounded_box_ex uses (x1, y1, x2, y2) instead of (x, y, w, h)
|
||||||
$window,
|
$x2 = $this->viewport->x + $this->viewport->width;
|
||||||
|
$y2 = $this->viewport->y + $this->viewport->height;
|
||||||
|
|
||||||
|
sdl_rounded_box_ex(
|
||||||
|
$renderer,
|
||||||
$this->viewport->x,
|
$this->viewport->x,
|
||||||
$this->viewport->y,
|
$this->viewport->y,
|
||||||
$this->viewport->width,
|
$x2,
|
||||||
$this->viewport->height,
|
$y2,
|
||||||
$border->roundTopLeft ?? 0,
|
|
||||||
$border->roundTopLeft ?? 0,
|
$border->roundTopLeft ?? 0,
|
||||||
$border->roundTopRight ?? 0,
|
$border->roundTopRight ?? 0,
|
||||||
$border->roundTopRight ?? 0,
|
|
||||||
$border->roundBottomLeft ?? 0,
|
|
||||||
$border->roundBottomLeft ?? 0,
|
|
||||||
$border->roundBottomRight ?? 0,
|
|
||||||
$border->roundBottomRight ?? 0,
|
$border->roundBottomRight ?? 0,
|
||||||
|
$border->roundBottomLeft ?? 0,
|
||||||
|
$bg->color->red,
|
||||||
|
$bg->color->green,
|
||||||
|
$bg->color->blue,
|
||||||
|
$bg->color->alpha,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
rsgl_drawRectF(
|
sdl_render_fill_rect(
|
||||||
$window,
|
$renderer,
|
||||||
$this->viewport->x,
|
[
|
||||||
$this->viewport->y,
|
'x' => $this->viewport->x,
|
||||||
$this->viewport->width,
|
'y' => $this->viewport->y,
|
||||||
$this->viewport->height,
|
'w' => $this->viewport->width,
|
||||||
|
'h' => $this->viewport->height,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderContent(&$window, null|TextRenderer $textRenderer = null): void
|
public function renderContent(&$renderer, null|TextRenderer $textRenderer = null): void
|
||||||
{
|
{
|
||||||
if (!$this->visible) {
|
if (!$this->visible) {
|
||||||
return;
|
return;
|
||||||
@ -156,8 +174,8 @@ abstract class Component
|
|||||||
|
|
||||||
// Render children
|
// Render children
|
||||||
foreach ($this->children as $child) {
|
foreach ($this->children as $child) {
|
||||||
$child->render($window, $textRenderer);
|
$child->render($renderer, $textRenderer);
|
||||||
$child->renderContent($window, $textRenderer);
|
$child->renderContent($renderer, $textRenderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,4 +252,32 @@ abstract class Component
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle text input event
|
||||||
|
* @param string $text The input text
|
||||||
|
*/
|
||||||
|
public function handleTextInput(string $text): void
|
||||||
|
{
|
||||||
|
// Default implementation: propagate to children
|
||||||
|
foreach ($this->children as $child) {
|
||||||
|
$child->handleTextInput($text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle key down event
|
||||||
|
* @param int $keycode SDL keycode
|
||||||
|
* @return bool True if event was handled
|
||||||
|
*/
|
||||||
|
public function handleKeyDown(int $keycode): bool
|
||||||
|
{
|
||||||
|
// Default implementation: propagate to children
|
||||||
|
foreach ($this->children as $child) {
|
||||||
|
if ($child->handleKeyDown($keycode)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
110
src/Ui/Widget/Checkbox.php
Normal file
110
src/Ui/Widget/Checkbox.php
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PHPNative\Ui\Widget;
|
||||||
|
|
||||||
|
use PHPNative\Framework\TextRenderer;
|
||||||
|
use PHPNative\Ui\Component;
|
||||||
|
|
||||||
|
class Checkbox extends Component
|
||||||
|
{
|
||||||
|
private bool $checked = false;
|
||||||
|
private $onChange = null;
|
||||||
|
private string $labelText = '';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
string $label = '',
|
||||||
|
bool $checked = false,
|
||||||
|
string $style = '',
|
||||||
|
$onChange = null,
|
||||||
|
) {
|
||||||
|
parent::__construct($style);
|
||||||
|
|
||||||
|
$this->checked = $checked;
|
||||||
|
$this->onChange = $onChange;
|
||||||
|
$this->labelText = $label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isChecked(): bool
|
||||||
|
{
|
||||||
|
return $this->checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setChecked(bool $checked): void
|
||||||
|
{
|
||||||
|
$this->checked = $checked;
|
||||||
|
|
||||||
|
if ($this->onChange !== null) {
|
||||||
|
($this->onChange)($checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOnChange(callable $onChange): void
|
||||||
|
{
|
||||||
|
$this->onChange = $onChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleMouseClick(float $mouseX, float $mouseY, int $button): bool
|
||||||
|
{
|
||||||
|
// Check if click is within checkbox bounds (not label)
|
||||||
|
$checkboxSize = 20;
|
||||||
|
if (
|
||||||
|
$mouseX >= $this->viewport->x &&
|
||||||
|
$mouseX <= ($this->viewport->x + $checkboxSize) &&
|
||||||
|
$mouseY >= $this->viewport->y &&
|
||||||
|
$mouseY <= ($this->viewport->y + $checkboxSize)
|
||||||
|
) {
|
||||||
|
$this->checked = !$this->checked;
|
||||||
|
|
||||||
|
if ($this->onChange !== null) {
|
||||||
|
($this->onChange)($this->checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::handleMouseClick($mouseX, $mouseY, $button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(&$renderer, null|TextRenderer $textRenderer = null): void
|
||||||
|
{
|
||||||
|
$checkboxSize = 20;
|
||||||
|
|
||||||
|
// Draw checkbox border
|
||||||
|
sdl_set_render_draw_color($renderer, 156, 163, 175, 255); // Gray-400
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $this->viewport->x,
|
||||||
|
'y' => $this->viewport->y,
|
||||||
|
'w' => $checkboxSize,
|
||||||
|
'h' => $checkboxSize,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Draw white background
|
||||||
|
sdl_set_render_draw_color($renderer, 255, 255, 255, 255);
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $this->viewport->x + 2,
|
||||||
|
'y' => $this->viewport->y + 2,
|
||||||
|
'w' => $checkboxSize - 4,
|
||||||
|
'h' => $checkboxSize - 4,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Draw checkmark if checked
|
||||||
|
if ($this->checked) {
|
||||||
|
sdl_set_render_draw_color($renderer, 37, 99, 235, 255); // Blue-600
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $this->viewport->x + 4,
|
||||||
|
'y' => $this->viewport->y + 4,
|
||||||
|
'w' => $checkboxSize - 8,
|
||||||
|
'h' => $checkboxSize - 8,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render label text if present
|
||||||
|
if (!empty($this->labelText) && $textRenderer !== null && $textRenderer->isInitialized()) {
|
||||||
|
$textX = $this->viewport->x + $checkboxSize + 8; // Checkbox + margin
|
||||||
|
$textY = $this->viewport->y + 2;
|
||||||
|
|
||||||
|
$textRenderer->setColor(0, 0, 0, 1.0); // Black
|
||||||
|
$textRenderer->drawText($this->labelText, (int) $textX, (int) $textY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -38,6 +38,18 @@ class Container extends Component
|
|||||||
parent::__construct($style);
|
parent::__construct($style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all child components
|
||||||
|
*/
|
||||||
|
public function clearChildren(): void
|
||||||
|
{
|
||||||
|
$this->children = [];
|
||||||
|
$this->contentWidth = 0;
|
||||||
|
$this->contentHeight = 0;
|
||||||
|
$this->scrollX = 0;
|
||||||
|
$this->scrollY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public function layout(null|TextRenderer $textRenderer = null): void
|
public function layout(null|TextRenderer $textRenderer = null): void
|
||||||
{
|
{
|
||||||
// Call parent to compute styles and setup viewports
|
// Call parent to compute styles and setup viewports
|
||||||
@ -131,9 +143,10 @@ class Container extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$hasExplicitHeight) {
|
if (!$hasExplicitHeight) {
|
||||||
// Set viewport to min(contentSize + padding, availableSize)
|
// Set viewport to content height + padding (don't expand to fill available space unnecessarily)
|
||||||
$desiredHeight = $this->contentHeight + $paddingY;
|
$desiredHeight = $this->contentHeight + $paddingY;
|
||||||
$this->viewport->height = (int) min($desiredHeight, $availableHeight);
|
// Only limit to availableHeight if we're not trying to measure natural size
|
||||||
|
$this->viewport->height = (int) $desiredHeight;
|
||||||
$this->contentViewport->height = max(0, $this->viewport->height - ((int) $paddingY));
|
$this->contentViewport->height = max(0, $this->viewport->height - ((int) $paddingY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,18 +199,20 @@ class Container extends Component
|
|||||||
|
|
||||||
if (!$hasExplicitSize) {
|
if (!$hasExplicitSize) {
|
||||||
// Need to measure natural size - do a temporary layout
|
// Need to measure natural size - do a temporary layout
|
||||||
|
// For flex-col without explicit height, give minimal space to measure intrinsic size
|
||||||
|
// For flex-row without explicit width, give minimal space to measure intrinsic size
|
||||||
$tempViewport = new Viewport(
|
$tempViewport = new Viewport(
|
||||||
x: $this->contentViewport->x,
|
x: $this->contentViewport->x,
|
||||||
y: $this->contentViewport->y,
|
y: $this->contentViewport->y,
|
||||||
width: $isRow ? $availableSpace : $this->contentViewport->width,
|
width: $isRow ? 9999 : $this->contentViewport->width,
|
||||||
height: $isRow ? $this->contentViewport->height : $availableSpace,
|
height: $isRow ? $this->contentViewport->height : 9999,
|
||||||
windowWidth: $this->contentViewport->windowWidth,
|
windowWidth: $this->contentViewport->windowWidth,
|
||||||
windowHeight: $this->contentViewport->windowHeight,
|
windowHeight: $this->contentViewport->windowHeight,
|
||||||
);
|
);
|
||||||
$child->setViewport($tempViewport);
|
$child->setViewport($tempViewport);
|
||||||
$child->layout($textRenderer);
|
$child->layout($textRenderer);
|
||||||
|
|
||||||
// Get natural size
|
// Get natural size (the actual size the child computed after layout)
|
||||||
$size = $isRow ? $child->getViewport()->width : $child->getViewport()->height;
|
$size = $isRow ? $child->getViewport()->width : $child->getViewport()->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +324,7 @@ class Container extends Component
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderContent(&$window, null|TextRenderer $textRenderer = null): void
|
public function renderContent(&$renderer, null|TextRenderer $textRenderer = null): void
|
||||||
{
|
{
|
||||||
if (!$this->visible) {
|
if (!$this->visible) {
|
||||||
return;
|
return;
|
||||||
@ -322,25 +337,21 @@ class Container extends Component
|
|||||||
|
|
||||||
// Apply scroll offset to children
|
// Apply scroll offset to children
|
||||||
if ($overflow['x'] || $overflow['y']) {
|
if ($overflow['x'] || $overflow['y']) {
|
||||||
// Enable scissor test for clipping
|
// Enable clipping
|
||||||
$scissorX = (int) $this->contentViewport->x;
|
$scissorX = (int) $this->contentViewport->x;
|
||||||
$scissorY = (int) $this->contentViewport->y;
|
$scissorY = (int) $this->contentViewport->y;
|
||||||
$scissorW = (int) $this->contentViewport->width;
|
$scissorW = (int) $this->contentViewport->width;
|
||||||
$scissorH = (int) $this->contentViewport->height;
|
$scissorH = (int) $this->contentViewport->height;
|
||||||
|
|
||||||
// IMPORTANT: RSGL uses batch rendering!
|
// SDL3: Set clip rect for clipping
|
||||||
// We need to flush the batch before/after scissor to ensure correct clipping
|
sdl_set_render_clip_rect($renderer, [
|
||||||
|
'x' => $scissorX,
|
||||||
|
'y' => $scissorY,
|
||||||
|
'w' => $scissorW,
|
||||||
|
'h' => $scissorH
|
||||||
|
]);
|
||||||
|
|
||||||
// Step 1: Flush any pending draw calls before scissor
|
// Render children with scroll offset
|
||||||
rsgl_render($window);
|
|
||||||
|
|
||||||
// Step 2: Enable scissor test for clipping
|
|
||||||
$windowHeight = $this->contentViewport->windowHeight;
|
|
||||||
$invertedY = $windowHeight - ($scissorY + $scissorH);
|
|
||||||
|
|
||||||
rsgl_scissorStart($window, $scissorX, $invertedY, $scissorW, $scissorH);
|
|
||||||
|
|
||||||
// Step 3: Render children with scroll offset (batches draw calls)
|
|
||||||
foreach ($this->children as $child) {
|
foreach ($this->children as $child) {
|
||||||
// Apply scroll offset recursively to child and all its descendants
|
// Apply scroll offset recursively to child and all its descendants
|
||||||
$child->applyScrollOffset((int) $this->scrollX, (int) $this->scrollY);
|
$child->applyScrollOffset((int) $this->scrollX, (int) $this->scrollY);
|
||||||
@ -354,30 +365,26 @@ class Container extends Component
|
|||||||
$childViewport->y < ($scissorY + $scissorH);
|
$childViewport->y < ($scissorY + $scissorH);
|
||||||
|
|
||||||
if ($isVisible) {
|
if ($isVisible) {
|
||||||
// Render - batches draw calls
|
$child->render($renderer, $textRenderer);
|
||||||
$child->render($textRenderer);
|
$child->renderContent($renderer, $textRenderer);
|
||||||
$child->renderContent($textRenderer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore by applying negative offset
|
// Restore by applying negative offset
|
||||||
$child->applyScrollOffset((int) -$this->scrollX, (int) -$this->scrollY);
|
$child->applyScrollOffset((int) -$this->scrollX, (int) -$this->scrollY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Flush the batch while scissor is still active
|
// Disable clipping
|
||||||
rsgl_render($window);
|
sdl_set_render_clip_rect($renderer, null);
|
||||||
|
|
||||||
// Step 5: Disable scissor test
|
|
||||||
rsgl_scissorEnd($window);
|
|
||||||
|
|
||||||
// Render scrollbars
|
// Render scrollbars
|
||||||
$this->renderScrollbars($overflow);
|
$this->renderScrollbars($renderer, $overflow);
|
||||||
} else {
|
} else {
|
||||||
// No overflow, render normally
|
// No overflow, render normally
|
||||||
parent::renderContent($window, $textRenderer);
|
parent::renderContent($renderer, $textRenderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderScrollbars(array $overflow): void
|
private function renderScrollbars(&$renderer, array $overflow): void
|
||||||
{
|
{
|
||||||
$scrollbarColor = [100, 100, 100, 200]; // Gray with some transparency
|
$scrollbarColor = [100, 100, 100, 200]; // Gray with some transparency
|
||||||
|
|
||||||
@ -394,32 +401,32 @@ class Container extends Component
|
|||||||
$scrollbarX = ($this->contentViewport->x + $this->contentViewport->width) - self::SCROLLBAR_WIDTH;
|
$scrollbarX = ($this->contentViewport->x + $this->contentViewport->width) - self::SCROLLBAR_WIDTH;
|
||||||
|
|
||||||
// Track
|
// Track
|
||||||
rsgl_setColor($this->window, 200, 200, 200, 100);
|
sdl_set_render_draw_color($renderer, 200, 200, 200, 100);
|
||||||
rsgl_drawRectF(
|
sdl_render_fill_rect(
|
||||||
$this->window,
|
$renderer,
|
||||||
(int) $scrollbarX,
|
[
|
||||||
(int) $this->contentViewport->y,
|
'x' => (int) $scrollbarX,
|
||||||
(int) self::SCROLLBAR_WIDTH,
|
'y' => (int) $this->contentViewport->y,
|
||||||
(int) $scrollbarHeight,
|
'w' => (int) self::SCROLLBAR_WIDTH,
|
||||||
|
'h' => (int) $scrollbarHeight,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Thumb
|
// Thumb - using sdl_rounded_box for rounded rectangle
|
||||||
rsgl_setColor(
|
$thumbX = (int) ($scrollbarX + 2);
|
||||||
$this->window,
|
$thumbW = (int) (self::SCROLLBAR_WIDTH - 4);
|
||||||
|
sdl_rounded_box(
|
||||||
|
$renderer,
|
||||||
|
$thumbX,
|
||||||
|
(int) $thumbY,
|
||||||
|
$thumbX + $thumbW,
|
||||||
|
(int) ($thumbY + $thumbHeight),
|
||||||
|
4,
|
||||||
$scrollbarColor[0],
|
$scrollbarColor[0],
|
||||||
$scrollbarColor[1],
|
$scrollbarColor[1],
|
||||||
$scrollbarColor[2],
|
$scrollbarColor[2],
|
||||||
$scrollbarColor[3],
|
$scrollbarColor[3],
|
||||||
);
|
);
|
||||||
rsgl_drawRoundRectF(
|
|
||||||
$this->window,
|
|
||||||
(int) ($scrollbarX + 2),
|
|
||||||
(int) $thumbY,
|
|
||||||
(int) (self::SCROLLBAR_WIDTH - 4),
|
|
||||||
(int) $thumbHeight,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Horizontal scrollbar
|
// Horizontal scrollbar
|
||||||
@ -435,32 +442,32 @@ class Container extends Component
|
|||||||
$scrollbarY = ($this->contentViewport->y + $this->contentViewport->height) - self::SCROLLBAR_WIDTH;
|
$scrollbarY = ($this->contentViewport->y + $this->contentViewport->height) - self::SCROLLBAR_WIDTH;
|
||||||
|
|
||||||
// Track
|
// Track
|
||||||
rsgl_setColor($this->window, 200, 200, 200, 100);
|
sdl_set_render_draw_color($renderer, 200, 200, 200, 100);
|
||||||
rsgl_drawRectF(
|
sdl_render_fill_rect(
|
||||||
$this->window,
|
$renderer,
|
||||||
(int) $this->contentViewport->x,
|
[
|
||||||
(int) $scrollbarY,
|
'x' => (int) $this->contentViewport->x,
|
||||||
(int) $scrollbarWidth,
|
'y' => (int) $scrollbarY,
|
||||||
(int) self::SCROLLBAR_WIDTH,
|
'w' => (int) $scrollbarWidth,
|
||||||
|
'h' => (int) self::SCROLLBAR_WIDTH,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Thumb
|
// Thumb - using sdl_rounded_box for rounded rectangle
|
||||||
rsgl_setColor(
|
$thumbY = (int) ($scrollbarY + 2);
|
||||||
$this->window,
|
$thumbH = (int) (self::SCROLLBAR_WIDTH - 4);
|
||||||
|
sdl_rounded_box(
|
||||||
|
$renderer,
|
||||||
|
(int) $thumbX,
|
||||||
|
$thumbY,
|
||||||
|
(int) ($thumbX + $thumbWidth),
|
||||||
|
$thumbY + $thumbH,
|
||||||
|
4,
|
||||||
$scrollbarColor[0],
|
$scrollbarColor[0],
|
||||||
$scrollbarColor[1],
|
$scrollbarColor[1],
|
||||||
$scrollbarColor[2],
|
$scrollbarColor[2],
|
||||||
$scrollbarColor[3],
|
$scrollbarColor[3],
|
||||||
);
|
);
|
||||||
rsgl_drawRoundRectF(
|
|
||||||
$this->window,
|
|
||||||
(int) $thumbX,
|
|
||||||
(int) ($scrollbarY + 2),
|
|
||||||
(int) $thumbWidth,
|
|
||||||
(int) (self::SCROLLBAR_WIDTH - 4),
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,9 @@ class Label extends Component
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
public string $text = '',
|
public string $text = '',
|
||||||
public string $style = '',
|
public string $style = '',
|
||||||
) {}
|
) {
|
||||||
|
parent::__construct($style);
|
||||||
|
}
|
||||||
|
|
||||||
public function setText(string $text): void
|
public function setText(string $text): void
|
||||||
{
|
{
|
||||||
|
|||||||
246
src/Ui/Widget/TextInput.php
Normal file
246
src/Ui/Widget/TextInput.php
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PHPNative\Ui\Widget;
|
||||||
|
|
||||||
|
use PHPNative\Framework\TextRenderer;
|
||||||
|
|
||||||
|
class TextInput extends Container
|
||||||
|
{
|
||||||
|
private string $value = '';
|
||||||
|
private string $placeholder = '';
|
||||||
|
private bool $focused = false;
|
||||||
|
private $onChange = null;
|
||||||
|
private int $cursorPosition = 0;
|
||||||
|
private float $cursorBlinkTime = 0;
|
||||||
|
private bool $cursorVisible = true;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
string $placeholder = '',
|
||||||
|
string $style = '',
|
||||||
|
$onChange = null,
|
||||||
|
) {
|
||||||
|
parent::__construct($style);
|
||||||
|
|
||||||
|
$this->placeholder = $placeholder;
|
||||||
|
$this->onChange = $onChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function layout(null|TextRenderer $textRenderer = null): void
|
||||||
|
{
|
||||||
|
// Parse styles first to get computed styles
|
||||||
|
$this->computedStyles = \PHPNative\Tailwind\StyleParser::parse($this->style)->getValidStyles(
|
||||||
|
\PHPNative\Tailwind\Style\MediaQueryEnum::normal,
|
||||||
|
\PHPNative\Tailwind\Style\StateEnum::normal,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Call parent layout
|
||||||
|
parent::layout($textRenderer);
|
||||||
|
|
||||||
|
// If no explicit height is set, calculate based on text size + padding
|
||||||
|
if (!isset($this->computedStyles[\PHPNative\Tailwind\Style\Height::class])) {
|
||||||
|
$padding = $this->computedStyles[\PHPNative\Tailwind\Style\Padding::class] ?? null;
|
||||||
|
$paddingY = $padding ? ($padding->top + $padding->bottom) : 0;
|
||||||
|
|
||||||
|
// Calculate text height
|
||||||
|
$textHeight = 16; // Default font size
|
||||||
|
if ($textRenderer !== null && $textRenderer->isInitialized()) {
|
||||||
|
$displayText = empty($this->value) ? ($this->placeholder ?: 'A') : 'A';
|
||||||
|
$size = $textRenderer->measureText($displayText);
|
||||||
|
$textHeight = $size[1] ?? 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set height to text height + padding + borders (2px * 2)
|
||||||
|
$this->viewport->height = (int) ($textHeight + $paddingY + 4);
|
||||||
|
$this->contentViewport->height = max(0, (int) ($textHeight + $paddingY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue(): string
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setValue(string $value): void
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
$this->cursorPosition = mb_strlen($value);
|
||||||
|
|
||||||
|
if ($this->onChange !== null) {
|
||||||
|
($this->onChange)($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOnChange(callable $onChange): void
|
||||||
|
{
|
||||||
|
$this->onChange = $onChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleMouseClick(float $mouseX, float $mouseY, int $button): bool
|
||||||
|
{
|
||||||
|
// Check if click is within bounds
|
||||||
|
if (
|
||||||
|
$mouseX >= $this->viewport->x &&
|
||||||
|
$mouseX <= ($this->viewport->x + $this->viewport->width) &&
|
||||||
|
$mouseY >= $this->viewport->y &&
|
||||||
|
$mouseY <= ($this->viewport->y + $this->viewport->height)
|
||||||
|
) {
|
||||||
|
$this->focused = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
$this->focused = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleTextInput(string $text): void
|
||||||
|
{
|
||||||
|
if (!$this->focused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert text at cursor position
|
||||||
|
$before = mb_substr($this->value, 0, $this->cursorPosition);
|
||||||
|
$after = mb_substr($this->value, $this->cursorPosition);
|
||||||
|
$this->value = $before . $text . $after;
|
||||||
|
$this->cursorPosition += mb_strlen($text);
|
||||||
|
|
||||||
|
if ($this->onChange !== null) {
|
||||||
|
($this->onChange)($this->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleKeyDown(int $keycode): bool
|
||||||
|
{
|
||||||
|
if (!$this->focused) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($keycode) {
|
||||||
|
case SDLK_BACKSPACE:
|
||||||
|
if ($this->cursorPosition > 0) {
|
||||||
|
$before = mb_substr($this->value, 0, $this->cursorPosition - 1);
|
||||||
|
$after = mb_substr($this->value, $this->cursorPosition);
|
||||||
|
$this->value = $before . $after;
|
||||||
|
$this->cursorPosition--;
|
||||||
|
|
||||||
|
if ($this->onChange !== null) {
|
||||||
|
($this->onChange)($this->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SDLK_DELETE:
|
||||||
|
if ($this->cursorPosition < mb_strlen($this->value)) {
|
||||||
|
$before = mb_substr($this->value, 0, $this->cursorPosition);
|
||||||
|
$after = mb_substr($this->value, $this->cursorPosition + 1);
|
||||||
|
$this->value = $before . $after;
|
||||||
|
|
||||||
|
if ($this->onChange !== null) {
|
||||||
|
($this->onChange)($this->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SDLK_LEFT:
|
||||||
|
if ($this->cursorPosition > 0) {
|
||||||
|
$this->cursorPosition--;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
if ($this->cursorPosition < mb_strlen($this->value)) {
|
||||||
|
$this->cursorPosition++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case SDLK_RETURN:
|
||||||
|
// Enter key - can be handled by parent
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isFocused(): bool
|
||||||
|
{
|
||||||
|
return $this->focused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function focus(): void
|
||||||
|
{
|
||||||
|
$this->focused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function blur(): void
|
||||||
|
{
|
||||||
|
$this->focused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(&$renderer, null|TextRenderer $textRenderer = null): void
|
||||||
|
{
|
||||||
|
// Render background with focus indicator
|
||||||
|
if ($this->focused) {
|
||||||
|
// Focused: blue border
|
||||||
|
sdl_set_render_draw_color($renderer, 59, 130, 246, 255); // Blue-500
|
||||||
|
} else {
|
||||||
|
// Not focused: gray border
|
||||||
|
sdl_set_render_draw_color($renderer, 209, 213, 219, 255); // Gray-300
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw border
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $this->viewport->x,
|
||||||
|
'y' => $this->viewport->y,
|
||||||
|
'w' => $this->viewport->width,
|
||||||
|
'h' => $this->viewport->height,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Draw white background inside
|
||||||
|
sdl_set_render_draw_color($renderer, 255, 255, 255, 255);
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $this->viewport->x + 2,
|
||||||
|
'y' => $this->viewport->y + 2,
|
||||||
|
'w' => $this->viewport->width - 4,
|
||||||
|
'h' => $this->viewport->height - 4,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Render text or placeholder
|
||||||
|
if ($textRenderer !== null && $textRenderer->isInitialized()) {
|
||||||
|
$displayText = empty($this->value) ? $this->placeholder : $this->value;
|
||||||
|
$textX = $this->viewport->x + 6;
|
||||||
|
$textY = $this->viewport->y + 6;
|
||||||
|
|
||||||
|
// Set color: gray for placeholder, black for text
|
||||||
|
if (empty($this->value)) {
|
||||||
|
$textRenderer->setColor(156/255, 163/255, 175/255, 1.0); // Gray-400
|
||||||
|
} else {
|
||||||
|
$textRenderer->setColor(0, 0, 0, 1.0); // Black
|
||||||
|
}
|
||||||
|
|
||||||
|
$textRenderer->drawText($displayText, (int) $textX, (int) $textY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render cursor if focused
|
||||||
|
if ($this->focused && $this->cursorVisible && $textRenderer) {
|
||||||
|
// Calculate cursor position
|
||||||
|
$textBeforeCursor = mb_substr($this->value, 0, $this->cursorPosition);
|
||||||
|
$cursorX = $this->viewport->x + 6; // Left padding
|
||||||
|
|
||||||
|
if (!empty($textBeforeCursor)) {
|
||||||
|
$size = $textRenderer->measureText($textBeforeCursor);
|
||||||
|
$cursorX += $size[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw cursor
|
||||||
|
sdl_set_render_draw_color($renderer, 0, 0, 0, 255);
|
||||||
|
sdl_render_fill_rect($renderer, [
|
||||||
|
'x' => $cursorX,
|
||||||
|
'y' => $this->viewport->y + 4,
|
||||||
|
'w' => 2,
|
||||||
|
'h' => $this->viewport->height - 8,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't render children - we handle text rendering directly
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,8 @@ use PHPNative\Framework\TextRenderer;
|
|||||||
class Window
|
class Window
|
||||||
{
|
{
|
||||||
private mixed $window = null;
|
private mixed $window = null;
|
||||||
|
private mixed $renderer = null;
|
||||||
|
private int $windowId = 0;
|
||||||
private null|Component $rootComponent = null;
|
private null|Component $rootComponent = null;
|
||||||
private ?TextRenderer $textRenderer;
|
private ?TextRenderer $textRenderer;
|
||||||
private float $mouseX = 0;
|
private float $mouseX = 0;
|
||||||
@ -24,25 +26,50 @@ class Window
|
|||||||
private int $x = 100,
|
private int $x = 100,
|
||||||
private int $y = 100,
|
private int $y = 100,
|
||||||
) {
|
) {
|
||||||
// Create window
|
// Initialize SDL if not already done
|
||||||
$this->window = rgfw_createWindow($title, $x, $y, $width, $height, 0);
|
static $sdlInitialized = false;
|
||||||
if (!$this->window) {
|
if (!$sdlInitialized) {
|
||||||
throw new \Exception('Failed to create window');
|
if (!sdl_init(SDL_INIT_VIDEO)) {
|
||||||
|
throw new \Exception('Failed to initialize SDL: ' . sdl_get_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize RSGL renderer
|
// Initialize TTF
|
||||||
if (!rsgl_init($this->window)) {
|
if (!ttf_init()) {
|
||||||
throw new \Exception('Failed to initialize RSGL renderer');
|
throw new \Exception('Failed to initialize TTF: ' . sdl_get_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
$sdlInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create window with resizable flag for normal window decorations
|
||||||
|
// SDL_WINDOW_RESIZABLE gives you the standard window controls (close, minimize, maximize)
|
||||||
|
$flags = 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get window ID for event routing
|
||||||
|
$this->windowId = sdl_get_window_id($this->window);
|
||||||
|
|
||||||
|
// Enable text input for this window
|
||||||
|
sdl_start_text_input($this->window);
|
||||||
|
|
||||||
|
// Create renderer
|
||||||
|
$this->renderer = sdl_create_renderer($this->window);
|
||||||
|
if (!$this->renderer) {
|
||||||
|
throw new \Exception('Failed to create renderer: ' . sdl_get_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize text renderer
|
// Initialize text renderer
|
||||||
$this->textRenderer = new TextRenderer($this->window);
|
$this->textRenderer = new TextRenderer($this->renderer);
|
||||||
if (!$this->textRenderer->init()) {
|
if (!$this->textRenderer->init()) {
|
||||||
error_log('Warning: Failed to initialize text renderer. Text rendering will not be available.');
|
error_log('Warning: Failed to initialize text renderer. Text rendering will not be available.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get actual window size
|
// Get actual window size
|
||||||
$size = rgfw_window_getSize($this->window);
|
$size = sdl_get_window_size($this->window);
|
||||||
$this->width = $size[0];
|
$this->width = $size[0];
|
||||||
$this->height = $size[1];
|
$this->height = $size[1];
|
||||||
$this->viewport = new Viewport(
|
$this->viewport = new Viewport(
|
||||||
@ -88,7 +115,7 @@ class Window
|
|||||||
|
|
||||||
public function shouldClose(): bool
|
public function shouldClose(): bool
|
||||||
{
|
{
|
||||||
return $this->shouldClose || rgfw_window_shouldClose($this->window);
|
return $this->shouldClose;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function close(): void
|
public function close(): void
|
||||||
@ -101,48 +128,69 @@ class Window
|
|||||||
return $this->window;
|
return $this->window;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getRendererResource(): mixed
|
||||||
* Handle window and input events
|
{
|
||||||
*/
|
return $this->renderer;
|
||||||
public function handleEvents(): void
|
}
|
||||||
|
|
||||||
|
public function getWindowId(): int
|
||||||
|
{
|
||||||
|
return $this->windowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a single event for this window
|
||||||
|
* Called by Application with pre-filtered events
|
||||||
|
*/
|
||||||
|
public function processEvent(array $event): void
|
||||||
{
|
{
|
||||||
while ($event = rgfw_window_checkQueuedEvent($this->window)) {
|
|
||||||
// Debug output - can be removed later
|
// Debug output - can be removed later
|
||||||
if (defined('DEBUG_EVENTS') && DEBUG_EVENTS) {
|
if (defined('DEBUG_EVENTS') && DEBUG_EVENTS) {
|
||||||
$eventTypes = [
|
$eventTypes = [
|
||||||
RGFW_quit => 'QUIT',
|
SDL_EVENT_QUIT => 'QUIT',
|
||||||
RGFW_keyPressed => 'KEY_PRESSED',
|
SDL_EVENT_WINDOW_CLOSE_REQUESTED => 'WINDOW_CLOSE_REQUESTED',
|
||||||
RGFW_mouseButtonPressed => 'MOUSE_PRESSED',
|
SDL_EVENT_KEY_DOWN => 'KEY_DOWN',
|
||||||
RGFW_mouseButtonReleased => 'MOUSE_RELEASED',
|
SDL_EVENT_MOUSE_BUTTON_DOWN => 'MOUSE_BUTTON_DOWN',
|
||||||
RGFW_mousePosChanged => 'MOUSE_MOVE',
|
SDL_EVENT_MOUSE_BUTTON_UP => 'MOUSE_BUTTON_UP',
|
||||||
|
SDL_EVENT_MOUSE_MOTION => 'MOUSE_MOTION',
|
||||||
|
SDL_EVENT_WINDOW_RESIZED => 'WINDOW_RESIZED',
|
||||||
];
|
];
|
||||||
$typeName = $eventTypes[$event['type']] ?? ('UNKNOWN(' . $event['type'] . ')');
|
$typeName = $eventTypes[$event['type']] ?? ('UNKNOWN(' . $event['type'] . ')');
|
||||||
error_log("[{$this->title}] Event: {$typeName}");
|
error_log("[{$this->title}] (ID:{$this->windowId}) Event: {$typeName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($event['type']) {
|
switch ($event['type']) {
|
||||||
case RGFW_quit:
|
case SDL_EVENT_QUIT:
|
||||||
|
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||||
$this->shouldClose = true;
|
$this->shouldClose = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RGFW_keyPressed:
|
case SDL_EVENT_KEY_DOWN:
|
||||||
$keyCode = $event['keyCode'] ?? 0;
|
$keycode = $event['keycode'] ?? 0;
|
||||||
if ($keyCode == RGFW_Escape) {
|
|
||||||
$this->shouldClose = true;
|
// Propagate key event to root component
|
||||||
|
if ($this->rootComponent) {
|
||||||
|
$this->rootComponent->handleKeyDown($keycode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RGFW_windowResized:
|
case SDL_EVENT_TEXT_INPUT:
|
||||||
|
$text = $event['text'] ?? '';
|
||||||
|
|
||||||
|
// Propagate text input to root component
|
||||||
|
if ($this->rootComponent && !empty($text)) {
|
||||||
|
$this->rootComponent->handleTextInput($text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_WINDOW_RESIZED:
|
||||||
// Update window dimensions (from event data)
|
// Update window dimensions (from event data)
|
||||||
$newWidth = $event[0] ?? $this->width;
|
$newWidth = $event['data1'] ?? $this->width;
|
||||||
$newHeight = $event[1] ?? $this->height;
|
$newHeight = $event['data2'] ?? $this->height;
|
||||||
|
|
||||||
$this->width = $newWidth;
|
$this->width = $newWidth;
|
||||||
$this->height = $newHeight;
|
$this->height = $newHeight;
|
||||||
|
|
||||||
// Update RSGL renderer size and viewport
|
|
||||||
rsgl_updateRendererSize($this->window);
|
|
||||||
|
|
||||||
// Update text renderer framebuffer
|
// Update text renderer framebuffer
|
||||||
if ($this->textRenderer && $this->textRenderer->isInitialized()) {
|
if ($this->textRenderer && $this->textRenderer->isInitialized()) {
|
||||||
$this->textRenderer->updateFramebuffer($newWidth, $newHeight);
|
$this->textRenderer->updateFramebuffer($newWidth, $newHeight);
|
||||||
@ -157,9 +205,9 @@ class Window
|
|||||||
$this->shouldBeReLayouted = true;
|
$this->shouldBeReLayouted = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RGFW_mousePosChanged:
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
$this->mouseX = $event[0] ?? 0;
|
$this->mouseX = $event['x'] ?? 0;
|
||||||
$this->mouseY = $event[1] ?? 0;
|
$this->mouseY = $event['y'] ?? 0;
|
||||||
|
|
||||||
// Propagate mouse move to root component
|
// Propagate mouse move to root component
|
||||||
if ($this->rootComponent) {
|
if ($this->rootComponent) {
|
||||||
@ -167,7 +215,7 @@ class Window
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RGFW_mouseButtonPressed:
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
$button = $event['button'] ?? 0;
|
$button = $event['button'] ?? 0;
|
||||||
// Propagate click to root component
|
// Propagate click to root component
|
||||||
if ($this->rootComponent) {
|
if ($this->rootComponent) {
|
||||||
@ -175,7 +223,7 @@ class Window
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RGFW_mouseButtonReleased:
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||||
$button = $event['button'] ?? 0;
|
$button = $event['button'] ?? 0;
|
||||||
|
|
||||||
// Propagate release to root component
|
// Propagate release to root component
|
||||||
@ -184,8 +232,8 @@ class Window
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RGFW_mouseScroll:
|
case SDL_EVENT_MOUSE_WHEEL:
|
||||||
$deltaY = $event[1] ?? 0;
|
$deltaY = $event['y'] ?? 0;
|
||||||
|
|
||||||
// Propagate wheel to root component
|
// Propagate wheel to root component
|
||||||
if ($this->rootComponent) {
|
if ($this->rootComponent) {
|
||||||
@ -194,7 +242,6 @@ class Window
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update mouse position and hover states
|
* Update mouse position and hover states
|
||||||
@ -202,36 +249,9 @@ class Window
|
|||||||
*/
|
*/
|
||||||
public function updateMousePosition(): void
|
public function updateMousePosition(): void
|
||||||
{
|
{
|
||||||
if (!$this->rootComponent) {
|
// With SDL3, mouse position is tracked through SDL_EVENT_MOUSE_MOTION events
|
||||||
return;
|
// This method is kept for compatibility but does nothing
|
||||||
}
|
// Hover states are updated in handleEvents() via SDL_EVENT_MOUSE_MOTION
|
||||||
|
|
||||||
// Try to get current mouse position relative to this window
|
|
||||||
if (function_exists('rgfw_window_getMousePoint')) {
|
|
||||||
$mousePos = rgfw_window_getMousePoint($this->window);
|
|
||||||
if ($mousePos !== false && is_array($mousePos)) {
|
|
||||||
$newX = $mousePos[0] ?? $this->mouseX;
|
|
||||||
$newY = $mousePos[1] ?? $this->mouseY;
|
|
||||||
|
|
||||||
// Only update if position changed to avoid unnecessary updates
|
|
||||||
if ($newX !== $this->mouseX || $newY !== $this->mouseY) {
|
|
||||||
$this->mouseX = $newX;
|
|
||||||
$this->mouseY = $newY;
|
|
||||||
$this->rootComponent->handleMouseMove($this->mouseX, $this->mouseY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// rgfw_window_getMousePoint() not available
|
|
||||||
// Hover will only work when window receives mouse events
|
|
||||||
// This is normal OS behavior - only focused windows get mouse events
|
|
||||||
static $warningShown = false;
|
|
||||||
if (!$warningShown && defined('DEBUG_EVENTS') && DEBUG_EVENTS) {
|
|
||||||
error_log(
|
|
||||||
'Note: rgfw_window_getMousePoint() not available. Hover states will only work for focused windows.',
|
|
||||||
);
|
|
||||||
$warningShown = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -266,20 +286,19 @@ class Window
|
|||||||
*/
|
*/
|
||||||
public function render(): void
|
public function render(): void
|
||||||
{
|
{
|
||||||
// Always clear the window to prevent black screens (white background, fully opaque)
|
// Clear the window with white background
|
||||||
|
sdl_set_render_draw_color($this->renderer, 255, 255, 255, 255);
|
||||||
|
sdl_render_clear($this->renderer);
|
||||||
|
|
||||||
// Only render content if window has been laid out
|
// Only render content if window has been laid out
|
||||||
// This can happen when windows are created during async callbacks
|
// This can happen when windows are created during async callbacks
|
||||||
if ($this->hasBeenLaidOut && $this->rootComponent) {
|
if ($this->hasBeenLaidOut && $this->rootComponent) {
|
||||||
rgfw_window_makeCurrent($this->window);
|
$this->rootComponent->render($this->renderer, $this->textRenderer);
|
||||||
rsgl_clear($this->window, 255, 255, 255, 255);
|
$this->rootComponent->renderContent($this->renderer, $this->textRenderer);
|
||||||
$this->rootComponent->render($this->window, $this->textRenderer);
|
|
||||||
$this->rootComponent->renderContent($this->window, $this->textRenderer);
|
|
||||||
rsgl_render($this->window);
|
|
||||||
rgfw_window_swapBuffers($this->window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always swap buffers to display the cleared window
|
// Present the rendered content
|
||||||
|
sdl_render_present($this->renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -293,6 +312,27 @@ class Window
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the window and all resources
|
||||||
|
* This explicitly closes the SDL window
|
||||||
|
*/
|
||||||
|
public function destroy(): void
|
||||||
|
{
|
||||||
|
// First clean up text renderer
|
||||||
|
$this->cleanup();
|
||||||
|
|
||||||
|
// Explicitly destroy SDL renderer and window
|
||||||
|
if ($this->renderer) {
|
||||||
|
sdl_destroy_renderer($this->renderer);
|
||||||
|
$this->renderer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->window) {
|
||||||
|
sdl_destroy_window($this->window);
|
||||||
|
$this->window = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function setShouldBeReLayouted(bool $shouldBeReLayouted): void
|
public function setShouldBeReLayouted(bool $shouldBeReLayouted): void
|
||||||
{
|
{
|
||||||
$this->shouldBeReLayouted = $shouldBeReLayouted;
|
$this->shouldBeReLayouted = $shouldBeReLayouted;
|
||||||
|
|||||||
43
test_multi_window.php
Normal file
43
test_multi_window.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
use PHPNative\Framework\Application;
|
||||||
|
use PHPNative\Ui\Window;
|
||||||
|
use PHPNative\Ui\Widget\Button;
|
||||||
|
use PHPNative\Ui\Widget\Container;
|
||||||
|
|
||||||
|
define('DEBUG_EVENTS', true); // Enable event debugging
|
||||||
|
|
||||||
|
$app = new Application();
|
||||||
|
|
||||||
|
// Main window
|
||||||
|
$mainWindow = new Window('Main Window', 400, 300);
|
||||||
|
$mainContainer = new Container('flex flex-col p-4 bg-gray-100');
|
||||||
|
|
||||||
|
$openButton = new Button('Open Second Window', 'bg-blue-500 text-white p-4 m-2 rounded hover:bg-blue-600');
|
||||||
|
$openButton->setOnClick(function() use ($app) {
|
||||||
|
echo "Creating second window...\n";
|
||||||
|
$secondWindow = new Window('Second Window', 400, 300);
|
||||||
|
$secondContainer = new Container('flex flex-col p-4 bg-green-100');
|
||||||
|
|
||||||
|
$closeButton = new Button('Close This Window', 'bg-red-500 text-white p-4 m-2 rounded hover:bg-red-600');
|
||||||
|
$closeButton->setOnClick(function() use ($secondWindow) {
|
||||||
|
echo "Close button clicked in second window (ID: {$secondWindow->getWindowId()})\n";
|
||||||
|
$secondWindow->close();
|
||||||
|
});
|
||||||
|
|
||||||
|
$secondContainer->addComponent($closeButton);
|
||||||
|
$secondWindow->setRoot($secondContainer);
|
||||||
|
$app->addWindow($secondWindow);
|
||||||
|
|
||||||
|
echo "Second window created with ID: {$secondWindow->getWindowId()}\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
$mainContainer->addComponent($openButton);
|
||||||
|
$mainWindow->setRoot($mainContainer);
|
||||||
|
$app->addWindow($mainWindow);
|
||||||
|
|
||||||
|
echo "Main window ID: {$mainWindow->getWindowId()}\n";
|
||||||
|
|
||||||
|
$app->run();
|
||||||
@ -1,75 +0,0 @@
|
|||||||
<?php
|
|
||||||
/* Test multi-window with event queue mode */
|
|
||||||
|
|
||||||
// Enable event queue mode
|
|
||||||
rgfw_setQueueEvents(true);
|
|
||||||
|
|
||||||
$win1 = rgfw_createWindow("Window 1", 100, 100, 400, 300, 0);
|
|
||||||
$win2 = rgfw_createWindow("Window 2", 550, 100, 400, 300, 0);
|
|
||||||
|
|
||||||
rsgl_init($win1);
|
|
||||||
rsgl_init($win2);
|
|
||||||
|
|
||||||
echo "Event queue mode enabled. Testing with 2 windows...\n";
|
|
||||||
echo "Try clicking in each window to test mouse events\n";
|
|
||||||
|
|
||||||
$running = true;
|
|
||||||
$frameCount = 0;
|
|
||||||
|
|
||||||
while ($running) {
|
|
||||||
// Poll events for all windows
|
|
||||||
rgfw_pollEvents();
|
|
||||||
|
|
||||||
// Check events for window 1
|
|
||||||
while ($event = rgfw_window_checkQueuedEvent($win1)) {
|
|
||||||
echo "Window 1 - Event type: {$event['type']}\n";
|
|
||||||
|
|
||||||
if ($event['type'] == RGFW_quit) {
|
|
||||||
$running = false;
|
|
||||||
} elseif ($event['type'] == RGFW_mouseButtonPressed) {
|
|
||||||
echo " Window 1 - Mouse clicked! Button: {$event['button']}\n";
|
|
||||||
} elseif ($event['type'] == RGFW_mousePosChanged) {
|
|
||||||
echo " Window 1 - Mouse moved to: {$event[0]}, {$event[1]}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check events for window 2
|
|
||||||
while ($event = rgfw_window_checkQueuedEvent($win2)) {
|
|
||||||
echo "Window 2 - Event type: {$event['type']}\n";
|
|
||||||
|
|
||||||
if ($event['type'] == RGFW_quit) {
|
|
||||||
$running = false;
|
|
||||||
} elseif ($event['type'] == RGFW_mouseButtonPressed) {
|
|
||||||
echo " Window 2 - Mouse clicked! Button: {$event['button']}\n";
|
|
||||||
} elseif ($event['type'] == RGFW_mousePosChanged) {
|
|
||||||
echo " Window 2 - Mouse moved to: {$event[0]}, {$event[1]}\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render window 1 (red background)
|
|
||||||
rsgl_clear($win1, 255, 0, 0, 255);
|
|
||||||
rsgl_drawRectF($win1, 150, 100, 100, 100);
|
|
||||||
rgfw_window_swapBuffers($win1);
|
|
||||||
|
|
||||||
// Render window 2 (blue background)
|
|
||||||
rsgl_clear($win2, 0, 0, 255, 255);
|
|
||||||
rsgl_drawRectF($win2, 150, 100, 100, 100);
|
|
||||||
rgfw_window_swapBuffers($win2);
|
|
||||||
|
|
||||||
$frameCount++;
|
|
||||||
if ($frameCount % 100 == 0) {
|
|
||||||
echo "Frame $frameCount - Both windows running\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if windows should close
|
|
||||||
if (rgfw_window_shouldClose($win1) || rgfw_window_shouldClose($win2)) {
|
|
||||||
$running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
usleep(16000); // ~60 FPS
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Test finished after $frameCount frames\n";
|
|
||||||
|
|
||||||
rgfw_window_close($win1);
|
|
||||||
rgfw_window_close($win2);
|
|
||||||
Loading…
Reference in New Issue
Block a user