Backup
This commit is contained in:
parent
c567194b1c
commit
c38bffd4f9
@ -3,10 +3,14 @@
|
||||
namespace ServerManager\UI;
|
||||
|
||||
use PHPNative\Framework\Settings;
|
||||
use PHPNative\Tailwind\Data\Icon as IconName;
|
||||
use PHPNative\Ui\Widget\Button;
|
||||
use PHPNative\Ui\Widget\Container;
|
||||
use PHPNative\Ui\Widget\Icon;
|
||||
use PHPNative\Ui\Widget\Label;
|
||||
use PHPNative\Ui\Widget\TextInput;
|
||||
use PHPNative\Ui\Widget\TextArea;
|
||||
use PHPNative\Ui\Widget\Modal;
|
||||
|
||||
class KanbanTab
|
||||
{
|
||||
@ -14,6 +18,12 @@ class KanbanTab
|
||||
private Settings $settings;
|
||||
private Container $boardsContainer;
|
||||
private TextInput $newBoardInput;
|
||||
private Modal $editModal;
|
||||
private TextInput $editTitleInput;
|
||||
private TextArea $editDetailsArea;
|
||||
private Container $editBoardButtonsContainer;
|
||||
private string $currentEditingBoard = 'neu';
|
||||
private null|string $currentEditingTaskId = null;
|
||||
|
||||
public function __construct(Settings $settings)
|
||||
{
|
||||
@ -69,6 +79,9 @@ class KanbanTab
|
||||
$kanbanTab->renderBoards();
|
||||
});
|
||||
|
||||
// Edit modal for tasks
|
||||
$this->createEditModal();
|
||||
|
||||
$this->renderBoards();
|
||||
}
|
||||
|
||||
@ -92,6 +105,173 @@ class KanbanTab
|
||||
}
|
||||
}
|
||||
|
||||
private function rebuildBoardButtons(): void
|
||||
{
|
||||
if (!isset($this->editBoardButtonsContainer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->editBoardButtonsContainer->clearChildren();
|
||||
|
||||
$boards = $this->settings->get('kanban.boards', []);
|
||||
if (!is_array($boards) || empty($boards)) {
|
||||
$boards = ['neu', 'in arbeit', 'fertig'];
|
||||
}
|
||||
|
||||
foreach ($boards as $boardName) {
|
||||
$isSelected = ($boardName === $this->currentEditingBoard);
|
||||
|
||||
$style = 'px-2 py-1 rounded text-xs border ';
|
||||
if ($isSelected) {
|
||||
$style .= 'bg-blue-600 text-white border-blue-600';
|
||||
} else {
|
||||
$style .= 'bg-white text-gray-700 border-gray-300 hover:bg-gray-100';
|
||||
}
|
||||
|
||||
$button = new Button($boardName, $style);
|
||||
|
||||
$kanbanTab = $this;
|
||||
$button->setOnClick(function () use ($kanbanTab, $boardName) {
|
||||
$kanbanTab->currentEditingBoard = $boardName;
|
||||
$kanbanTab->rebuildBoardButtons();
|
||||
});
|
||||
|
||||
$this->editBoardButtonsContainer->addComponent($button);
|
||||
}
|
||||
}
|
||||
|
||||
private function createEditModal(): void
|
||||
{
|
||||
$content = new Container('flex flex-col bg-white rounded-lg shadow-xl p-4 gap-3 w-[480] max-h-[420]');
|
||||
$content->setUseTextureCache(false);
|
||||
|
||||
$content->addComponent(new Label('Task bearbeiten', 'text-lg font-bold text-black'));
|
||||
|
||||
// Title
|
||||
$content->addComponent(new Label('Titel', 'text-xs text-gray-600'));
|
||||
$this->editTitleInput = new TextInput(
|
||||
'Titel',
|
||||
'w-full border border-gray-300 rounded px-3 py-2 bg-white text-black text-sm',
|
||||
);
|
||||
$content->addComponent($this->editTitleInput);
|
||||
|
||||
// Details
|
||||
$content->addComponent(new Label('Details', 'text-xs text-gray-600'));
|
||||
$this->editDetailsArea = new TextArea(
|
||||
'',
|
||||
'Details...',
|
||||
'flex-1 border border-gray-300 rounded px-3 py-2 bg-white text-black text-xs',
|
||||
);
|
||||
$this->editDetailsArea->setUseTextureCache(false);
|
||||
$content->addComponent($this->editDetailsArea);
|
||||
|
||||
// Board selection (selectbox-artig)
|
||||
$content->addComponent(new Label('Board', 'text-xs text-gray-600'));
|
||||
$this->editBoardButtonsContainer = new Container('flex flex-row flex-wrap gap-1');
|
||||
$this->rebuildBoardButtons();
|
||||
$content->addComponent($this->editBoardButtonsContainer);
|
||||
|
||||
// Buttons
|
||||
$buttonRow = new Container('flex flex-row justify-end gap-2 mt-2');
|
||||
$cancelButton = new Button(
|
||||
'Abbrechen',
|
||||
'px-3 py-2 bg-gray-300 rounded hover:bg-gray-400',
|
||||
null,
|
||||
'text-black text-sm',
|
||||
);
|
||||
$saveButton = new Button(
|
||||
'Speichern',
|
||||
'px-3 py-2 bg-green-600 rounded hover:bg-green-700',
|
||||
null,
|
||||
'text-white text-sm',
|
||||
);
|
||||
|
||||
$kanbanTab = $this;
|
||||
$cancelButton->setOnClick(function () use ($kanbanTab) {
|
||||
$kanbanTab->editModal->setVisible(false);
|
||||
});
|
||||
$saveButton->setOnClick(function () use ($kanbanTab) {
|
||||
$kanbanTab->saveEditedTask();
|
||||
});
|
||||
|
||||
$buttonRow->addComponent($cancelButton);
|
||||
$buttonRow->addComponent($saveButton);
|
||||
$content->addComponent($buttonRow);
|
||||
|
||||
$this->editModal = new Modal($content);
|
||||
$this->tab->addComponent($this->editModal);
|
||||
}
|
||||
|
||||
private function openEditModal(array $task): void
|
||||
{
|
||||
$this->currentEditingTaskId = $task['id'] ?? null;
|
||||
if ($this->currentEditingTaskId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$title = (string) ($task['title'] ?? '');
|
||||
$details = (string) ($task['details'] ?? '');
|
||||
$board = (string) ($task['board'] ?? 'neu');
|
||||
|
||||
$this->editTitleInput->setValue($title);
|
||||
$this->editDetailsArea->setValue($details);
|
||||
$this->currentEditingBoard = $board;
|
||||
$this->rebuildBoardButtons();
|
||||
|
||||
$this->editModal->setVisible(true);
|
||||
}
|
||||
|
||||
private function saveEditedTask(): void
|
||||
{
|
||||
if ($this->currentEditingTaskId === null) {
|
||||
$this->editModal->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
$title = trim($this->editTitleInput->getValue());
|
||||
$details = trim($this->editDetailsArea->getValue());
|
||||
$board = trim($this->currentEditingBoard);
|
||||
|
||||
if ($title === '') {
|
||||
$title = 'Ohne Titel';
|
||||
}
|
||||
|
||||
if ($board === '') {
|
||||
$board = 'neu';
|
||||
}
|
||||
|
||||
$tasks = $this->settings->get('kanban.tasks', []);
|
||||
if (!is_array($tasks)) {
|
||||
$tasks = [];
|
||||
}
|
||||
|
||||
foreach ($tasks as &$task) {
|
||||
if (($task['id'] ?? null) === $this->currentEditingTaskId) {
|
||||
$task['title'] = $title;
|
||||
$task['details'] = $details;
|
||||
$task['board'] = $board;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unset($task);
|
||||
|
||||
// Ensure board exists
|
||||
$boards = $this->settings->get('kanban.boards', []);
|
||||
if (!is_array($boards)) {
|
||||
$boards = [];
|
||||
}
|
||||
if (!in_array($board, $boards, true)) {
|
||||
$boards[] = $board;
|
||||
$this->settings->set('kanban.boards', $boards);
|
||||
}
|
||||
|
||||
$this->settings->set('kanban.tasks', $tasks);
|
||||
$this->settings->save();
|
||||
|
||||
$this->editModal->setVisible(false);
|
||||
$this->renderBoards();
|
||||
}
|
||||
|
||||
private function renderBoards(): void
|
||||
{
|
||||
$this->boardsContainer->clearChildren();
|
||||
@ -127,11 +307,66 @@ class KanbanTab
|
||||
$title = (string) ($task['title'] ?? '');
|
||||
$serverId = $task['server_id'] ?? null;
|
||||
$serverLabel = $serverId !== null ? ('Server #' . $serverId) : 'Kein Server';
|
||||
$taskId = $task['id'] ?? null;
|
||||
|
||||
$card = new Container(
|
||||
'flex flex-col gap-1 px-3 py-2 bg-white border border-gray-200 rounded shadow-sm',
|
||||
);
|
||||
$card->addComponent(new Label($title, 'text-xs text-gray-900'));
|
||||
|
||||
// Header row with title and action icons
|
||||
$headerRow = new Container('flex flex-row items-center gap-1');
|
||||
$headerRow->addComponent(new Label($title, 'text-xs text-gray-900 flex-1'));
|
||||
|
||||
// Edit icon button
|
||||
$editButton = new Button(
|
||||
'',
|
||||
'p-1 rounded hover:bg-blue-100',
|
||||
null,
|
||||
'text-blue-600',
|
||||
);
|
||||
$editIcon = new Icon(IconName::edit, 12, 'text-blue-600');
|
||||
$editButton->setIcon($editIcon);
|
||||
|
||||
$kanbanTab = $this;
|
||||
$editButton->setOnClick(function () use ($kanbanTab, $task) {
|
||||
$kanbanTab->openEditModal($task);
|
||||
});
|
||||
|
||||
// Delete icon button
|
||||
$deleteButton = new Button(
|
||||
'',
|
||||
'p-1 rounded hover:bg-red-100',
|
||||
null,
|
||||
'text-red-600',
|
||||
);
|
||||
$deleteIcon = new Icon(IconName::trash, 12, 'text-red-600');
|
||||
$deleteButton->setIcon($deleteIcon);
|
||||
|
||||
$deleteButton->setOnClick(function () use ($kanbanTab, $taskId) {
|
||||
if ($taskId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tasks = $kanbanTab->settings->get('kanban.tasks', []);
|
||||
if (!is_array($tasks)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tasks = array_values(array_filter(
|
||||
$tasks,
|
||||
static fn($t) => ($t['id'] ?? null) !== $taskId,
|
||||
));
|
||||
|
||||
$kanbanTab->settings->set('kanban.tasks', $tasks);
|
||||
$kanbanTab->settings->save();
|
||||
$kanbanTab->renderBoards();
|
||||
});
|
||||
|
||||
$headerRow->addComponent($editButton);
|
||||
$headerRow->addComponent($deleteButton);
|
||||
$card->addComponent($headerRow);
|
||||
|
||||
// Server label
|
||||
$card->addComponent(new Label($serverLabel, 'text-[10px] text-gray-500'));
|
||||
|
||||
$columnBody->addComponent($card);
|
||||
|
||||
@ -82,13 +82,13 @@ class ServerListTab
|
||||
// Bulk action buttons for selected servers
|
||||
$rebootButton = new Button(
|
||||
'Reboot ausgewählte',
|
||||
'px-3 py-2 bg-red-600 rounded hover:bg-red-700',
|
||||
'px-3 shadow-lg/50 py-2 bg-red-600 rounded hover:bg-red-700',
|
||||
null,
|
||||
'text-white',
|
||||
);
|
||||
$updateButton = new Button(
|
||||
'Update ausgewählte',
|
||||
'px-3 py-2 bg-amber-600 rounded hover:bg-amber-700',
|
||||
'px-3 shadow-lg/50 hover:shadow-red-600 py-2 bg-amber-600 rounded hover:bg-amber-700',
|
||||
null,
|
||||
'text-white',
|
||||
);
|
||||
@ -260,12 +260,7 @@ class ServerListTab
|
||||
'Neue Task...',
|
||||
'flex-1 border border-gray-300 rounded px-3 py-2 bg-white text-black',
|
||||
);
|
||||
$addTodoButton = new Button(
|
||||
'+',
|
||||
'px-3 py-2 bg-blue-600 rounded hover:bg-blue-700',
|
||||
null,
|
||||
'text-white',
|
||||
);
|
||||
$addTodoButton = new Button('+', 'px-3 py-2 bg-blue-600 rounded hover:bg-blue-700', null, 'text-white');
|
||||
$todoInputRow->addComponent($this->todoInput);
|
||||
$todoInputRow->addComponent($addTodoButton);
|
||||
$detailPanel->addComponent($todoInputRow);
|
||||
@ -306,7 +301,7 @@ class ServerListTab
|
||||
|
||||
// Load per-server settings (API key, todos)
|
||||
$serverId = $row['id'] ?? null;
|
||||
$serverListTab->currentServerId = is_numeric($serverId) ? (int) $serverId : null;
|
||||
$serverListTab->currentServerId = is_numeric($serverId) ? ((int) $serverId) : null;
|
||||
|
||||
if ($serverListTab->currentServerId !== null) {
|
||||
$settingsKeyBase = 'servers.' . $serverListTab->currentServerId;
|
||||
@ -388,20 +383,14 @@ class ServerListTab
|
||||
echo "Error: {$result['error']}\n";
|
||||
} elseif (isset($result['success'], $result['servers'])) {
|
||||
// Basisdaten setzen, Docker-Status initial auf "pending"
|
||||
$serverListTab->currentServerData = array_map(
|
||||
static fn($row) => array_merge(
|
||||
[
|
||||
'docker_status' => 'pending',
|
||||
'docker' => null,
|
||||
'docker_error' => null,
|
||||
'needs_reboot' => 'unbekannt',
|
||||
'updates_available' => 'unbekannt',
|
||||
'os_version' => 'unbekannt',
|
||||
],
|
||||
$row,
|
||||
),
|
||||
$result['servers'],
|
||||
);
|
||||
$serverListTab->currentServerData = array_map(static fn($row) => array_merge([
|
||||
'docker_status' => 'pending',
|
||||
'docker' => null,
|
||||
'docker_error' => null,
|
||||
'needs_reboot' => 'unbekannt',
|
||||
'updates_available' => 'unbekannt',
|
||||
'os_version' => 'unbekannt',
|
||||
], $row), $result['servers']);
|
||||
|
||||
$serverListTab->table->setData($serverListTab->currentServerData, false);
|
||||
$serverListTab->statusLabel->setText('Server geladen: ' . $result['count'] . ' gefunden');
|
||||
@ -788,9 +777,8 @@ class ServerListTab
|
||||
$serverListTab->settings->set($settingsKeyBase . '.api_key', $apiKey);
|
||||
$serverListTab->settings->save();
|
||||
|
||||
$serverListTab->statusLabel->setText(
|
||||
'Server-Einstellungen gespeichert für Server #' . $serverListTab->currentServerId,
|
||||
);
|
||||
$serverListTab->statusLabel->setText('Server-Einstellungen gespeichert für Server #' .
|
||||
$serverListTab->currentServerId);
|
||||
});
|
||||
|
||||
// Add TODO for current server
|
||||
@ -918,9 +906,7 @@ class ServerListTab
|
||||
$this->todoListContainer->clearChildren();
|
||||
|
||||
if (empty($this->currentServerTodos)) {
|
||||
$this->todoListContainer->addComponent(
|
||||
new Label('Keine Tasks', 'text-xs text-gray-500 italic'),
|
||||
);
|
||||
$this->todoListContainer->addComponent(new Label('Keine Tasks', 'text-xs text-gray-500 italic'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -929,10 +915,7 @@ class ServerListTab
|
||||
$board = (string) ($task['board'] ?? 'neu');
|
||||
|
||||
$row = new Container('flex flex-row items-center gap-2');
|
||||
$row->addComponent(new Label(
|
||||
'- ' . $title . ' [' . $board . ']',
|
||||
'text-xs text-gray-800 flex-1',
|
||||
));
|
||||
$row->addComponent(new Label('- ' . $title . ' [' . $board . ']', 'text-xs text-gray-800 flex-1'));
|
||||
|
||||
$removeButton = new Button(
|
||||
'x',
|
||||
@ -953,10 +936,7 @@ class ServerListTab
|
||||
return;
|
||||
}
|
||||
|
||||
$tasks = array_values(array_filter(
|
||||
$tasks,
|
||||
static fn($t) => ($t['id'] ?? null) !== $taskId,
|
||||
));
|
||||
$tasks = array_values(array_filter($tasks, static fn($t) => ($t['id'] ?? null) !== $taskId));
|
||||
|
||||
$serverListTab->settings->set('kanban.tasks', $tasks);
|
||||
$serverListTab->settings->save();
|
||||
@ -1010,12 +990,9 @@ class ServerListTab
|
||||
$tasks = [];
|
||||
}
|
||||
|
||||
$this->currentServerTodos = array_values(array_filter(
|
||||
$tasks,
|
||||
function ($task) {
|
||||
return (int) ($task['server_id'] ?? 0) === (int) $this->currentServerId;
|
||||
},
|
||||
));
|
||||
$this->currentServerTodos = array_values(array_filter($tasks, function ($task) {
|
||||
return ((int) ($task['server_id'] ?? 0)) === ((int) $this->currentServerId);
|
||||
}));
|
||||
|
||||
$this->renderTodoList();
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -3,4 +3,5 @@
|
||||
# Created by configure
|
||||
|
||||
'./configure' \
|
||||
'--enable-sdl3' \
|
||||
"$@"
|
||||
|
||||
@ -413,7 +413,7 @@ $config_headers
|
||||
|
||||
Report bugs to the package provider."
|
||||
|
||||
ac_cs_config=''
|
||||
ac_cs_config='--enable-sdl3'
|
||||
ac_cs_version="\
|
||||
config.status
|
||||
configured by ./configure, generated by GNU Autoconf 2.72,
|
||||
@ -494,7 +494,7 @@ if $ac_cs_silent; then
|
||||
fi
|
||||
|
||||
if $ac_cs_recheck; then
|
||||
set X /bin/bash './configure' $ac_configure_extra_args --no-create --no-recursion
|
||||
set X /bin/bash './configure' '--enable-sdl3' $ac_configure_extra_args --no-create --no-recursion
|
||||
shift
|
||||
\printf "%s\n" "running CONFIG_SHELL=/bin/bash $*" >&6
|
||||
CONFIG_SHELL='/bin/bash'
|
||||
|
||||
Binary file not shown.
159
php-sdl3/sdl3.c
159
php-sdl3/sdl3.c
@ -526,6 +526,153 @@ PHP_FUNCTION(sdl_set_texture_alpha_mod) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
PHP_FUNCTION(sdl_create_box_shadow_texture) {
|
||||
zval *ren_res;
|
||||
SDL_Renderer *renderer;
|
||||
zend_long width, height, blurRadius, alpha, r, g, b;
|
||||
|
||||
if (zend_parse_parameters(
|
||||
ZEND_NUM_ARGS(),
|
||||
"rlllllll",
|
||||
&ren_res,
|
||||
&width,
|
||||
&height,
|
||||
&blurRadius,
|
||||
&alpha,
|
||||
&r,
|
||||
&g,
|
||||
&b) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
renderer = (SDL_Renderer *)zend_fetch_resource(Z_RES_P(ren_res), "SDL_Renderer", le_sdl_renderer);
|
||||
if (!renderer) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
int w = (int) width;
|
||||
int h = (int) height;
|
||||
int radius = (int) blurRadius;
|
||||
if (radius < 0) {
|
||||
radius = 0;
|
||||
}
|
||||
if (alpha < 0) {
|
||||
alpha = 0;
|
||||
}
|
||||
if (alpha > 255) {
|
||||
alpha = 255;
|
||||
}
|
||||
|
||||
int size = w * h;
|
||||
Uint8 *alphaMap = emalloc(size * sizeof(Uint8));
|
||||
if (!alphaMap) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
memset(alphaMap, 0, size * sizeof(Uint8));
|
||||
|
||||
int margin = radius + 2;
|
||||
for (int y = margin; y < h - margin; y++) {
|
||||
int rowOffset = y * w;
|
||||
for (int x = margin; x < w - margin; x++) {
|
||||
alphaMap[rowOffset + x] = (Uint8) alpha;
|
||||
}
|
||||
}
|
||||
|
||||
if (radius > 0) {
|
||||
Uint8 *temp = emalloc(size * sizeof(Uint8));
|
||||
if (!temp) {
|
||||
efree(alphaMap);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// Horizontal blur
|
||||
for (int y = 0; y < h; y++) {
|
||||
int rowOffset = y * w;
|
||||
for (int x = 0; x < w; x++) {
|
||||
int sum = 0;
|
||||
int count = 0;
|
||||
int xStart = x - radius;
|
||||
int xEnd = x + radius;
|
||||
if (xStart < 0) xStart = 0;
|
||||
if (xEnd >= w) xEnd = w - 1;
|
||||
for (int xi = xStart; xi <= xEnd; xi++) {
|
||||
sum += alphaMap[rowOffset + xi];
|
||||
count++;
|
||||
}
|
||||
temp[rowOffset + x] = count > 0 ? (Uint8)(sum / count) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical blur
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int sum = 0;
|
||||
int count = 0;
|
||||
int yStart = y - radius;
|
||||
int yEnd = y + radius;
|
||||
if (yStart < 0) yStart = 0;
|
||||
if (yEnd >= h) yEnd = h - 1;
|
||||
for (int yi = yStart; yi <= yEnd; yi++) {
|
||||
sum += temp[yi * w + x];
|
||||
count++;
|
||||
}
|
||||
alphaMap[y * w + x] = count > 0 ? (Uint8)(sum / count) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
efree(temp);
|
||||
}
|
||||
|
||||
SDL_Texture *texture = SDL_CreateTexture(
|
||||
renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STATIC,
|
||||
w,
|
||||
h);
|
||||
|
||||
if (!texture) {
|
||||
efree(alphaMap);
|
||||
php_error_docref(NULL, E_WARNING, "Failed to create shadow texture: %s", SDL_GetError());
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
Uint32 *pixels = emalloc(size * sizeof(Uint32));
|
||||
if (!pixels) {
|
||||
efree(alphaMap);
|
||||
SDL_DestroyTexture(texture);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
Uint8 red = (Uint8) r;
|
||||
Uint8 green = (Uint8) g;
|
||||
Uint8 blue = (Uint8) b;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
Uint8 a = alphaMap[i];
|
||||
pixels[i] = ((Uint32)a << 24) | ((Uint32)red << 16) | ((Uint32)green << 8) | (Uint32)blue;
|
||||
}
|
||||
|
||||
if (SDL_UpdateTexture(texture, NULL, pixels, w * 4) < 0) {
|
||||
efree(alphaMap);
|
||||
efree(pixels);
|
||||
SDL_DestroyTexture(texture);
|
||||
php_error_docref(NULL, E_WARNING, "Failed to update shadow texture: %s", SDL_GetError());
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
efree(alphaMap);
|
||||
efree(pixels);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
|
||||
RETURN_RES(zend_register_resource(texture, le_sdl_texture));
|
||||
}
|
||||
|
||||
PHP_FUNCTION(sdl_get_render_target) {
|
||||
zval *ren_res;
|
||||
SDL_Renderer *renderer;
|
||||
@ -994,6 +1141,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_set_texture_alpha_mod, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, alpha)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_sdl_create_box_shadow_texture, 0, 0, 8)
|
||||
ZEND_ARG_INFO(0, renderer)
|
||||
ZEND_ARG_INFO(0, width)
|
||||
ZEND_ARG_INFO(0, height)
|
||||
ZEND_ARG_INFO(0, blurRadius)
|
||||
ZEND_ARG_INFO(0, alpha)
|
||||
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_sdl_get_render_target, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, renderer)
|
||||
ZEND_END_ARG_INFO()
|
||||
@ -1101,6 +1259,7 @@ const zend_function_entry sdl3_functions[] = {
|
||||
PHP_FE(sdl_update_texture, arginfo_sdl_update_texture)
|
||||
PHP_FE(sdl_set_texture_blend_mode, arginfo_sdl_set_texture_blend_mode)
|
||||
PHP_FE(sdl_set_texture_alpha_mod, arginfo_sdl_set_texture_alpha_mod)
|
||||
PHP_FE(sdl_create_box_shadow_texture, arginfo_sdl_create_box_shadow_texture)
|
||||
PHP_FE(sdl_get_render_target, arginfo_sdl_get_render_target)
|
||||
PHP_FE(sdl_set_render_target, arginfo_sdl_set_render_target)
|
||||
PHP_FE(sdl_rounded_box, arginfo_sdl_rounded_box)
|
||||
|
||||
@ -931,6 +931,22 @@ abstract class Component
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the optimized C helper is available, use it.
|
||||
if (function_exists('sdl_create_box_shadow_texture')) {
|
||||
return sdl_create_box_shadow_texture(
|
||||
$renderer,
|
||||
$width,
|
||||
$height,
|
||||
$blurRadius,
|
||||
$alpha,
|
||||
$r,
|
||||
$g,
|
||||
$b,
|
||||
);
|
||||
}
|
||||
|
||||
// Fallback: existing PHP implementation
|
||||
|
||||
// Create alpha map (single channel) - start with transparent
|
||||
$alphaMap = array_fill(0, $width * $height, 0);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user