git repos / blockattack-game

blame: source/code/theme_editor/ThemeEditorState.cpp

normal view · raw

727f4a09 Poul Sander 2026-05-24 21:47 1
/*
727f4a09 Poul Sander 2026-05-24 21:47 2
===========================================================================
727f4a09 Poul Sander 2026-05-24 21:47 3
blockattack - Block Attack - Rise of the Blocks
727f4a09 Poul Sander 2026-05-24 21:47 4
Copyright (C) 2005-2026 Poul Sander
727f4a09 Poul Sander 2026-05-24 21:47 5
727f4a09 Poul Sander 2026-05-24 21:47 6
This program is free software: you can redistribute it and/or modify
727f4a09 Poul Sander 2026-05-24 21:47 7
it under the terms of the GNU General Public License as published by
727f4a09 Poul Sander 2026-05-24 21:47 8
the Free Software Foundation, either version 2 of the License, or
727f4a09 Poul Sander 2026-05-24 21:47 9
(at your option) any later version.
727f4a09 Poul Sander 2026-05-24 21:47 10
727f4a09 Poul Sander 2026-05-24 21:47 11
This program is distributed in the hope that it will be useful,
727f4a09 Poul Sander 2026-05-24 21:47 12
but WITHOUT ANY WARRANTY; without even the implied warranty of
727f4a09 Poul Sander 2026-05-24 21:47 13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
727f4a09 Poul Sander 2026-05-24 21:47 14
GNU General Public License for more details.
727f4a09 Poul Sander 2026-05-24 21:47 15
727f4a09 Poul Sander 2026-05-24 21:47 16
You should have received a copy of the GNU General Public License
727f4a09 Poul Sander 2026-05-24 21:47 17
along with this program.  If not, see http://www.gnu.org/licenses/
727f4a09 Poul Sander 2026-05-24 21:47 18
727f4a09 Poul Sander 2026-05-24 21:47 19
Source information and contacts persons can be found at
727f4a09 Poul Sander 2026-05-24 21:47 20
https://blockattack.net
727f4a09 Poul Sander 2026-05-24 21:47 21
===========================================================================
727f4a09 Poul Sander 2026-05-24 21:47 22
*/
727f4a09 Poul Sander 2026-05-24 21:47 23
727f4a09 Poul Sander 2026-05-24 21:47 24
#include "ThemeEditorState.hpp"
727f4a09 Poul Sander 2026-05-24 21:47 25
727f4a09 Poul Sander 2026-05-24 21:47 26
#include <fmt/core.h>
727f4a09 Poul Sander 2026-05-24 21:47 27
#include <algorithm>
727f4a09 Poul Sander 2026-05-24 21:47 28
727f4a09 Poul Sander 2026-05-24 21:47 29
#include "imgui.h"
727f4a09 Poul Sander 2026-05-24 21:47 30
#include "imgui_internal.h"
727f4a09 Poul Sander 2026-05-24 21:47 31
#include "backends/imgui_impl_sdl2.h"
727f4a09 Poul Sander 2026-05-24 21:47 32
#include "backends/imgui_impl_sdlrenderer2.h"
727f4a09 Poul Sander 2026-05-24 21:47 33
#include "../sago/SagoMisc.hpp"
727f4a09 Poul Sander 2026-05-24 21:47 34
#include "../BlockGameSdl.hpp"
727f4a09 Poul Sander 2026-05-24 21:47 35
727f4a09 Poul Sander 2026-05-24 21:47 36
ThemeEditorState::ThemeEditorState() {
727f4a09 Poul Sander 2026-05-24 21:47 37
	current_border.name = "standard";
727f4a09 Poul Sander 2026-05-24 21:47 38
	current_border.border_sprite = "board_back_back";
727f4a09 Poul Sander 2026-05-24 21:47 39
	current_border.border_sprite_offset = {-60, -68};
727f4a09 Poul Sander 2026-05-24 21:47 40
	current_border.score_label_offset = {310, 80};
727f4a09 Poul Sander 2026-05-24 21:47 41
	current_border.time_label_offset = {310, 129};
727f4a09 Poul Sander 2026-05-24 21:47 42
	current_border.chain_label_offset = {310, 178};
727f4a09 Poul Sander 2026-05-24 21:47 43
	current_border.speed_label_offset = {310, 227};
727f4a09 Poul Sander 2026-05-24 21:47 44
	current_border.score_field_offset = {310, 102};
727f4a09 Poul Sander 2026-05-24 21:47 45
	current_border.time_field_offset = {310, 151};
727f4a09 Poul Sander 2026-05-24 21:47 46
	current_border.chain_field_offset = {310, 200};
727f4a09 Poul Sander 2026-05-24 21:47 47
	current_border.speed_field_offset = {310, 249};
727f4a09 Poul Sander 2026-05-24 21:47 48
727f4a09 Poul Sander 2026-05-24 21:47 49
	current_background.name = "standard";
727f4a09 Poul Sander 2026-05-24 21:47 50
	current_background.background_sprite = "background";
727f4a09 Poul Sander 2026-05-24 21:47 51
	current_background.background_sprite_16x9 = "background_sixteen_nine";
727f4a09 Poul Sander 2026-05-24 21:47 52
	current_background.background_scale = ImgScale::Stretch;
727f4a09 Poul Sander 2026-05-24 21:47 53
}
727f4a09 Poul Sander 2026-05-24 21:47 54
727f4a09 Poul Sander 2026-05-24 21:47 55
ThemeEditorState::~ThemeEditorState() {
727f4a09 Poul Sander 2026-05-24 21:47 56
	// Restore the original theme when editor exits
727f4a09 Poul Sander 2026-05-24 21:47 57
	globalData.theme = saved_theme;
727f4a09 Poul Sander 2026-05-24 21:47 58
}
727f4a09 Poul Sander 2026-05-24 21:47 59
727f4a09 Poul Sander 2026-05-24 21:47 60
bool ThemeEditorState::IsActive() {
727f4a09 Poul Sander 2026-05-24 21:47 61
	return isActive;
727f4a09 Poul Sander 2026-05-24 21:47 62
}
727f4a09 Poul Sander 2026-05-24 21:47 63
727f4a09 Poul Sander 2026-05-24 21:47 64
void ThemeEditorState::ProcessInput(const SDL_Event& event, bool& processed) {
727f4a09 Poul Sander 2026-05-24 21:47 65
	(void)event;
727f4a09 Poul Sander 2026-05-24 21:47 66
	(void)processed;
727f4a09 Poul Sander 2026-05-24 21:47 67
	// Handle any custom input processing here if needed
727f4a09 Poul Sander 2026-05-24 21:47 68
}
727f4a09 Poul Sander 2026-05-24 21:47 69
727f4a09 Poul Sander 2026-05-24 21:47 70
void ThemeEditorState::Init() {
727f4a09 Poul Sander 2026-05-24 21:47 71
	// Initialize the theme system
727f4a09 Poul Sander 2026-05-24 21:47 72
	ThemesInit();
727f4a09 Poul Sander 2026-05-24 21:47 73
727f4a09 Poul Sander 2026-05-24 21:47 74
	// Populate lists
727f4a09 Poul Sander 2026-05-24 21:47 75
	border_names = ThemesGetBorderNames();
727f4a09 Poul Sander 2026-05-24 21:47 76
	background_names = ThemesGetBackgroundNames();
727f4a09 Poul Sander 2026-05-24 21:47 77
	decoration_names = ThemesGetDecorationNames();
727f4a09 Poul Sander 2026-05-24 21:47 78
727f4a09 Poul Sander 2026-05-24 21:47 79
	// Save current theme and set up preview
727f4a09 Poul Sander 2026-05-24 21:47 80
	saved_theme = globalData.theme;
727f4a09 Poul Sander 2026-05-24 21:47 81
	preview_theme = ThemesGet(0);
727f4a09 Poul Sander 2026-05-24 21:47 82
727f4a09 Poul Sander 2026-05-24 21:47 83
	// Create preview game instance positioned in the right 40% of screen
727f4a09 Poul Sander 2026-05-24 21:47 84
	// Editor takes 60% of width, so preview starts at 60% + some padding
727f4a09 Poul Sander 2026-05-24 21:47 85
	int preview_x = static_cast<int>(globalData.xsize * 0.62f);
727f4a09 Poul Sander 2026-05-24 21:47 86
	preview_game = std::make_shared<BlockGameSdl>(preview_x, 100, &globalData.spriteHolder->GetDataHolder());
727f4a09 Poul Sander 2026-05-24 21:47 87
	preview_game->name = "Preview";
727f4a09 Poul Sander 2026-05-24 21:47 88
	preview_game->putSampleBlocks();
727f4a09 Poul Sander 2026-05-24 21:47 89
727f4a09 Poul Sander 2026-05-24 21:47 90
	// Initialize preview with current border/background
727f4a09 Poul Sander 2026-05-24 21:47 91
	preview_theme.border = current_border;
727f4a09 Poul Sander 2026-05-24 21:47 92
	preview_theme.background = current_background;
727f4a09 Poul Sander 2026-05-24 21:47 93
	globalData.theme = preview_theme;
727f4a09 Poul Sander 2026-05-24 21:47 94
}
727f4a09 Poul Sander 2026-05-24 21:47 95
727f4a09 Poul Sander 2026-05-24 21:47 96
void ThemeEditorState::Update() {
727f4a09 Poul Sander 2026-05-24 21:47 97
	// Update preview if needed
727f4a09 Poul Sander 2026-05-24 21:47 98
	if (preview_needs_update) {
727f4a09 Poul Sander 2026-05-24 21:47 99
		preview_needs_update = false;
727f4a09 Poul Sander 2026-05-24 21:47 100
		UpdatePreview();
727f4a09 Poul Sander 2026-05-24 21:47 101
	}
727f4a09 Poul Sander 2026-05-24 21:47 102
}
727f4a09 Poul Sander 2026-05-24 21:47 103
727f4a09 Poul Sander 2026-05-24 21:47 104
void ThemeEditorState::UpdatePreview() {
727f4a09 Poul Sander 2026-05-24 21:47 105
	// Update preview theme based on current tab
727f4a09 Poul Sander 2026-05-24 21:47 106
	switch (current_tab) {
727f4a09 Poul Sander 2026-05-24 21:47 107
		case 0: // Border Editor
727f4a09 Poul Sander 2026-05-24 21:47 108
			preview_theme.border = current_border;
727f4a09 Poul Sander 2026-05-24 21:47 109
			break;
727f4a09 Poul Sander 2026-05-24 21:47 110
		case 1: // Background Editor
727f4a09 Poul Sander 2026-05-24 21:47 111
			preview_theme.background = current_background;
727f4a09 Poul Sander 2026-05-24 21:47 112
			break;
727f4a09 Poul Sander 2026-05-24 21:47 113
		case 2: // Theme Composer
727f4a09 Poul Sander 2026-05-24 21:47 114
			// Combine selected components
727f4a09 Poul Sander 2026-05-24 21:47 115
			if (static_cast<size_t>(selected_border_index) < border_names.size()) {
727f4a09 Poul Sander 2026-05-24 21:47 116
				preview_theme.border = ThemesGetBorder(border_names[selected_border_index]);
727f4a09 Poul Sander 2026-05-24 21:47 117
			}
727f4a09 Poul Sander 2026-05-24 21:47 118
			if (static_cast<size_t>(selected_background_index) < background_names.size()) {
727f4a09 Poul Sander 2026-05-24 21:47 119
				preview_theme.background = ThemesGetBackground(background_names[selected_background_index]);
727f4a09 Poul Sander 2026-05-24 21:47 120
			}
727f4a09 Poul Sander 2026-05-24 21:47 121
			preview_theme.back_board = board_backgrounds[selected_board_background];
727f4a09 Poul Sander 2026-05-24 21:47 122
			break;
727f4a09 Poul Sander 2026-05-24 21:47 123
	}
727f4a09 Poul Sander 2026-05-24 21:47 124
727f4a09 Poul Sander 2026-05-24 21:47 125
	// Apply theme to global for preview rendering
727f4a09 Poul Sander 2026-05-24 21:47 126
	globalData.theme = preview_theme;
727f4a09 Poul Sander 2026-05-24 21:47 127
}
727f4a09 Poul Sander 2026-05-24 21:47 128
727f4a09 Poul Sander 2026-05-24 21:47 129
void ThemeEditorState::Draw(SDL_Renderer* target) {
727f4a09 Poul Sander 2026-05-24 21:47 130
	// Get actual physical renderer size and keep logicalResize in sync every frame
727f4a09 Poul Sander 2026-05-24 21:47 131
	int display_w = 1;
727f4a09 Poul Sander 2026-05-24 21:47 132
	int display_h = 1;
727f4a09 Poul Sander 2026-05-24 21:47 133
	SDL_GetRendererOutputSize(target, &display_w, &display_h);
727f4a09 Poul Sander 2026-05-24 21:47 134
	globalData.logicalResize.SetPhysicalSize(display_w, display_h);
727f4a09 Poul Sander 2026-05-24 21:47 135
727f4a09 Poul Sander 2026-05-24 21:47 136
	// Main window - take up left 60% of screen to leave room for preview
727f4a09 Poul Sander 2026-05-24 21:47 137
	const float editor_width = display_w * 0.5f;
727f4a09 Poul Sander 2026-05-24 21:47 138
	ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
727f4a09 Poul Sander 2026-05-24 21:47 139
	ImGui::SetNextWindowSize(ImVec2(editor_width, (float)display_h), ImGuiCond_Always);
727f4a09 Poul Sander 2026-05-24 21:47 140
727f4a09 Poul Sander 2026-05-24 21:47 141
	ImGui::Begin("Theme Editor", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
727f4a09 Poul Sander 2026-05-24 21:47 142
727f4a09 Poul Sander 2026-05-24 21:47 143
	// Tab bar
727f4a09 Poul Sander 2026-05-24 21:47 144
	if (ImGui::BeginTabBar("EditorTabs")) {
727f4a09 Poul Sander 2026-05-24 21:47 145
		if (ImGui::BeginTabItem("Border Editor")) {
727f4a09 Poul Sander 2026-05-24 21:47 146
			current_tab = 0;
727f4a09 Poul Sander 2026-05-24 21:47 147
			DrawBorderEditor();
727f4a09 Poul Sander 2026-05-24 21:47 148
			ImGui::EndTabItem();
727f4a09 Poul Sander 2026-05-24 21:47 149
		}
727f4a09 Poul Sander 2026-05-24 21:47 150
		if (ImGui::BeginTabItem("Background Editor")) {
727f4a09 Poul Sander 2026-05-24 21:47 151
			current_tab = 1;
727f4a09 Poul Sander 2026-05-24 21:47 152
			DrawBackgroundEditor();
727f4a09 Poul Sander 2026-05-24 21:47 153
			ImGui::EndTabItem();
727f4a09 Poul Sander 2026-05-24 21:47 154
		}
727f4a09 Poul Sander 2026-05-24 21:47 155
		if (ImGui::BeginTabItem("Theme Composer")) {
727f4a09 Poul Sander 2026-05-24 21:47 156
			current_tab = 2;
727f4a09 Poul Sander 2026-05-24 21:47 157
			DrawThemeComposer();
727f4a09 Poul Sander 2026-05-24 21:47 158
			ImGui::EndTabItem();
727f4a09 Poul Sander 2026-05-24 21:47 159
		}
727f4a09 Poul Sander 2026-05-24 21:47 160
		ImGui::EndTabBar();
727f4a09 Poul Sander 2026-05-24 21:47 161
	}
727f4a09 Poul Sander 2026-05-24 21:47 162
727f4a09 Poul Sander 2026-05-24 21:47 163
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 164
	if (ImGui::Button("Exit Editor")) {
727f4a09 Poul Sander 2026-05-24 21:47 165
		isActive = false;
727f4a09 Poul Sander 2026-05-24 21:47 166
	}
727f4a09 Poul Sander 2026-05-24 21:47 167
727f4a09 Poul Sander 2026-05-24 21:47 168
	ImGui::End();
727f4a09 Poul Sander 2026-05-24 21:47 169
727f4a09 Poul Sander 2026-05-24 21:47 170
	// Draw the preview: convert physical position (ImGui space) to logical space for DoPaintJob
727f4a09 Poul Sander 2026-05-24 21:47 171
	if (preview_game) {
727f4a09 Poul Sander 2026-05-24 21:47 172
		const int preview_physical_x = static_cast<int>(editor_width) + 250;
727f4a09 Poul Sander 2026-05-24 21:47 173
		const int preview_physical_y = 150;
727f4a09 Poul Sander 2026-05-24 21:47 174
		int preview_logical_x = 0;
727f4a09 Poul Sander 2026-05-24 21:47 175
		int preview_logical_y = 0;
727f4a09 Poul Sander 2026-05-24 21:47 176
		globalData.logicalResize.PhysicalToLogical(preview_physical_x, preview_physical_y, preview_logical_x, preview_logical_y);
727f4a09 Poul Sander 2026-05-24 21:47 177
		preview_game->SetTopXY(preview_logical_x, preview_logical_y);
727f4a09 Poul Sander 2026-05-24 21:47 178
		preview_game->DoPaintJob();
727f4a09 Poul Sander 2026-05-24 21:47 179
	}
727f4a09 Poul Sander 2026-05-24 21:47 180
}
727f4a09 Poul Sander 2026-05-24 21:47 181
727f4a09 Poul Sander 2026-05-24 21:47 182
void ThemeEditorState::DrawBorderEditor() {
727f4a09 Poul Sander 2026-05-24 21:47 183
	ImGui::Text("Create and edit custom borders");
727f4a09 Poul Sander 2026-05-24 21:47 184
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 185
727f4a09 Poul Sander 2026-05-24 21:47 186
	// Load existing border
727f4a09 Poul Sander 2026-05-24 21:47 187
	ImGui::Text("Load existing border:");
727f4a09 Poul Sander 2026-05-24 21:47 188
	if (ImGui::BeginCombo("##BorderLoad", border_names.empty() ? "No borders" : current_border.name.c_str())) {
727f4a09 Poul Sander 2026-05-24 21:47 189
		for (const auto& name : border_names) {
727f4a09 Poul Sander 2026-05-24 21:47 190
			bool is_selected = (current_border.name == name);
727f4a09 Poul Sander 2026-05-24 21:47 191
			if (ImGui::Selectable(name.c_str(), is_selected)) {
727f4a09 Poul Sander 2026-05-24 21:47 192
				LoadBorder(name);
727f4a09 Poul Sander 2026-05-24 21:47 193
			}
727f4a09 Poul Sander 2026-05-24 21:47 194
			if (is_selected) {
727f4a09 Poul Sander 2026-05-24 21:47 195
				ImGui::SetItemDefaultFocus();
727f4a09 Poul Sander 2026-05-24 21:47 196
			}
727f4a09 Poul Sander 2026-05-24 21:47 197
		}
727f4a09 Poul Sander 2026-05-24 21:47 198
		ImGui::EndCombo();
727f4a09 Poul Sander 2026-05-24 21:47 199
	}
727f4a09 Poul Sander 2026-05-24 21:47 200
727f4a09 Poul Sander 2026-05-24 21:47 201
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 202
	ImGui::Text("Border Settings:");
727f4a09 Poul Sander 2026-05-24 21:47 203
727f4a09 Poul Sander 2026-05-24 21:47 204
	// Border name
727f4a09 Poul Sander 2026-05-24 21:47 205
	ImGui::InputText("Border Name", border_name_buffer, sizeof(border_name_buffer));
727f4a09 Poul Sander 2026-05-24 21:47 206
727f4a09 Poul Sander 2026-05-24 21:47 207
	// Border sprite
727f4a09 Poul Sander 2026-05-24 21:47 208
	if (ImGui::InputText("Border Sprite", border_sprite_buffer, sizeof(border_sprite_buffer))) {
727f4a09 Poul Sander 2026-05-24 21:47 209
		current_border.border_sprite = border_sprite_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 210
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 211
	}
727f4a09 Poul Sander 2026-05-24 21:47 212
	if (ImGui::IsItemHovered()) {
727f4a09 Poul Sander 2026-05-24 21:47 213
		ImGui::SetTooltip("Examples: board_back_back, board_back_back_mirror");
727f4a09 Poul Sander 2026-05-24 21:47 214
	}
727f4a09 Poul Sander 2026-05-24 21:47 215
727f4a09 Poul Sander 2026-05-24 21:47 216
	// Validate sprite button
727f4a09 Poul Sander 2026-05-24 21:47 217
	ImGui::SameLine();
727f4a09 Poul Sander 2026-05-24 21:47 218
	if (ImGui::Button("Validate##border")) {
727f4a09 Poul Sander 2026-05-24 21:47 219
		if (ValidateSprite(border_sprite_buffer)) {
727f4a09 Poul Sander 2026-05-24 21:47 220
			ImGui::OpenPopup("Valid Sprite");
727f4a09 Poul Sander 2026-05-24 21:47 221
		} else {
727f4a09 Poul Sander 2026-05-24 21:47 222
			ImGui::OpenPopup("Invalid Sprite");
727f4a09 Poul Sander 2026-05-24 21:47 223
		}
727f4a09 Poul Sander 2026-05-24 21:47 224
	}
727f4a09 Poul Sander 2026-05-24 21:47 225
727f4a09 Poul Sander 2026-05-24 21:47 226
	if (ImGui::BeginPopup("Valid Sprite")) {
727f4a09 Poul Sander 2026-05-24 21:47 227
		ImGui::Text("Sprite exists!");
727f4a09 Poul Sander 2026-05-24 21:47 228
		ImGui::EndPopup();
727f4a09 Poul Sander 2026-05-24 21:47 229
	}
727f4a09 Poul Sander 2026-05-24 21:47 230
	if (ImGui::BeginPopup("Invalid Sprite")) {
727f4a09 Poul Sander 2026-05-24 21:47 231
		ImGui::Text("Warning: Sprite does not exist!");
727f4a09 Poul Sander 2026-05-24 21:47 232
		ImGui::EndPopup();
727f4a09 Poul Sander 2026-05-24 21:47 233
	}
727f4a09 Poul Sander 2026-05-24 21:47 234
727f4a09 Poul Sander 2026-05-24 21:47 235
	// Border sprite offset
727f4a09 Poul Sander 2026-05-24 21:47 236
	if (ImGui::DragInt2("Border Sprite Offset", &border_offset_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 237
		current_border.border_sprite_offset = {border_offset_x, border_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 238
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 239
	}
727f4a09 Poul Sander 2026-05-24 21:47 240
727f4a09 Poul Sander 2026-05-24 21:47 241
	// Label offsets
727f4a09 Poul Sander 2026-05-24 21:47 242
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 243
	ImGui::Text("Label Positions:");
727f4a09 Poul Sander 2026-05-24 21:47 244
	if (ImGui::DragInt2("Score Label Offset", &score_offset_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 245
		current_border.score_label_offset = {score_offset_x, score_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 246
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 247
	}
727f4a09 Poul Sander 2026-05-24 21:47 248
	if (ImGui::DragInt2("Time Label Offset", &time_offset_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 249
		current_border.time_label_offset = {time_offset_x, time_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 250
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 251
	}
727f4a09 Poul Sander 2026-05-24 21:47 252
	if (ImGui::DragInt2("Chain Label Offset", &chain_offset_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 253
		current_border.chain_label_offset = {chain_offset_x, chain_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 254
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 255
	}
727f4a09 Poul Sander 2026-05-24 21:47 256
	if (ImGui::DragInt2("Speed Label Offset", &speed_offset_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 257
		current_border.speed_label_offset = {speed_offset_x, speed_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 258
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 259
	}
727f4a09 Poul Sander 2026-05-24 21:47 260
727f4a09 Poul Sander 2026-05-24 21:47 261
	// Field offsets
727f4a09 Poul Sander 2026-05-24 21:47 262
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 263
	ImGui::Text("Field Positions:");
727f4a09 Poul Sander 2026-05-24 21:47 264
	if (ImGui::DragInt2("Score Field Offset", &score_field_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 265
		current_border.score_field_offset = {score_field_x, score_field_y};
727f4a09 Poul Sander 2026-05-24 21:47 266
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 267
	}
727f4a09 Poul Sander 2026-05-24 21:47 268
	if (ImGui::DragInt2("Time Field Offset", &time_field_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 269
		current_border.time_field_offset = {time_field_x, time_field_y};
727f4a09 Poul Sander 2026-05-24 21:47 270
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 271
	}
727f4a09 Poul Sander 2026-05-24 21:47 272
	if (ImGui::DragInt2("Chain Field Offset", &chain_field_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 273
		current_border.chain_field_offset = {chain_field_x, chain_field_y};
727f4a09 Poul Sander 2026-05-24 21:47 274
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 275
	}
727f4a09 Poul Sander 2026-05-24 21:47 276
	if (ImGui::DragInt2("Speed Field Offset", &speed_field_x)) {
727f4a09 Poul Sander 2026-05-24 21:47 277
		current_border.speed_field_offset = {speed_field_x, speed_field_y};
727f4a09 Poul Sander 2026-05-24 21:47 278
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 279
	}
727f4a09 Poul Sander 2026-05-24 21:47 280
727f4a09 Poul Sander 2026-05-24 21:47 281
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 282
	if (ImGui::Button("Save Border")) {
727f4a09 Poul Sander 2026-05-24 21:47 283
		SaveCurrentBorder();
727f4a09 Poul Sander 2026-05-24 21:47 284
	}
727f4a09 Poul Sander 2026-05-24 21:47 285
	ImGui::SameLine();
727f4a09 Poul Sander 2026-05-24 21:47 286
	ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Saved to: borders/<name>.json");
727f4a09 Poul Sander 2026-05-24 21:47 287
}
727f4a09 Poul Sander 2026-05-24 21:47 288
727f4a09 Poul Sander 2026-05-24 21:47 289
void ThemeEditorState::DrawBackgroundEditor() {
727f4a09 Poul Sander 2026-05-24 21:47 290
	ImGui::Text("Create and edit custom backgrounds");
727f4a09 Poul Sander 2026-05-24 21:47 291
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 292
727f4a09 Poul Sander 2026-05-24 21:47 293
	// Load existing background
727f4a09 Poul Sander 2026-05-24 21:47 294
	ImGui::Text("Load existing background:");
727f4a09 Poul Sander 2026-05-24 21:47 295
	if (ImGui::BeginCombo("##BackgroundLoad", background_names.empty() ? "No backgrounds" : current_background.name.c_str())) {
727f4a09 Poul Sander 2026-05-24 21:47 296
		for (const auto& name : background_names) {
727f4a09 Poul Sander 2026-05-24 21:47 297
			bool is_selected = (current_background.name == name);
727f4a09 Poul Sander 2026-05-24 21:47 298
			if (ImGui::Selectable(name.c_str(), is_selected)) {
727f4a09 Poul Sander 2026-05-24 21:47 299
				LoadBackground(name);
727f4a09 Poul Sander 2026-05-24 21:47 300
			}
727f4a09 Poul Sander 2026-05-24 21:47 301
			if (is_selected) {
727f4a09 Poul Sander 2026-05-24 21:47 302
				ImGui::SetItemDefaultFocus();
727f4a09 Poul Sander 2026-05-24 21:47 303
			}
727f4a09 Poul Sander 2026-05-24 21:47 304
		}
727f4a09 Poul Sander 2026-05-24 21:47 305
		ImGui::EndCombo();
727f4a09 Poul Sander 2026-05-24 21:47 306
	}
727f4a09 Poul Sander 2026-05-24 21:47 307
727f4a09 Poul Sander 2026-05-24 21:47 308
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 309
	ImGui::Text("Background Settings:");
727f4a09 Poul Sander 2026-05-24 21:47 310
727f4a09 Poul Sander 2026-05-24 21:47 311
	// Background name
727f4a09 Poul Sander 2026-05-24 21:47 312
	ImGui::InputText("Background Name", background_name_buffer, sizeof(background_name_buffer));
727f4a09 Poul Sander 2026-05-24 21:47 313
727f4a09 Poul Sander 2026-05-24 21:47 314
	// Background sprite
727f4a09 Poul Sander 2026-05-24 21:47 315
	if (ImGui::InputText("Background Sprite", background_sprite_buffer, sizeof(background_sprite_buffer))) {
727f4a09 Poul Sander 2026-05-24 21:47 316
		current_background.background_sprite = background_sprite_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 317
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 318
	}
727f4a09 Poul Sander 2026-05-24 21:47 319
	if (ImGui::IsItemHovered()) {
727f4a09 Poul Sander 2026-05-24 21:47 320
		ImGui::SetTooltip("Examples: background, background_autumn, custom_background_<filename>");
727f4a09 Poul Sander 2026-05-24 21:47 321
	}
727f4a09 Poul Sander 2026-05-24 21:47 322
727f4a09 Poul Sander 2026-05-24 21:47 323
	// Validate sprite button
727f4a09 Poul Sander 2026-05-24 21:47 324
	ImGui::SameLine();
727f4a09 Poul Sander 2026-05-24 21:47 325
	if (ImGui::Button("Validate##background")) {
727f4a09 Poul Sander 2026-05-24 21:47 326
		if (ValidateSprite(background_sprite_buffer)) {
727f4a09 Poul Sander 2026-05-24 21:47 327
			ImGui::OpenPopup("Valid BG Sprite");
727f4a09 Poul Sander 2026-05-24 21:47 328
		} else {
727f4a09 Poul Sander 2026-05-24 21:47 329
			ImGui::OpenPopup("Invalid BG Sprite");
727f4a09 Poul Sander 2026-05-24 21:47 330
		}
727f4a09 Poul Sander 2026-05-24 21:47 331
	}
727f4a09 Poul Sander 2026-05-24 21:47 332
727f4a09 Poul Sander 2026-05-24 21:47 333
	if (ImGui::BeginPopup("Valid BG Sprite")) {
727f4a09 Poul Sander 2026-05-24 21:47 334
		ImGui::Text("Sprite exists!");
727f4a09 Poul Sander 2026-05-24 21:47 335
		ImGui::EndPopup();
727f4a09 Poul Sander 2026-05-24 21:47 336
	}
727f4a09 Poul Sander 2026-05-24 21:47 337
	if (ImGui::BeginPopup("Invalid BG Sprite")) {
727f4a09 Poul Sander 2026-05-24 21:47 338
		ImGui::Text("Warning: Sprite does not exist!");
727f4a09 Poul Sander 2026-05-24 21:47 339
		ImGui::EndPopup();
727f4a09 Poul Sander 2026-05-24 21:47 340
	}
727f4a09 Poul Sander 2026-05-24 21:47 341
727f4a09 Poul Sander 2026-05-24 21:47 342
	// 16:9 background sprite (optional)
727f4a09 Poul Sander 2026-05-24 21:47 343
	if (ImGui::InputText("Background Sprite 16:9 (optional)", background_sprite_16x9_buffer, sizeof(background_sprite_16x9_buffer))) {
727f4a09 Poul Sander 2026-05-24 21:47 344
		current_background.background_sprite_16x9 = background_sprite_16x9_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 345
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 346
	}
727f4a09 Poul Sander 2026-05-24 21:47 347
727f4a09 Poul Sander 2026-05-24 21:47 348
	// Scaling mode
727f4a09 Poul Sander 2026-05-24 21:47 349
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 350
	ImGui::Text("Scaling Mode:");
727f4a09 Poul Sander 2026-05-24 21:47 351
	const char* scale_modes[] = { "Stretch", "Tile", "Resize", "Cut" };
727f4a09 Poul Sander 2026-05-24 21:47 352
	if (ImGui::Combo("##ScaleMode", &background_scale_mode, scale_modes, 4)) {
727f4a09 Poul Sander 2026-05-24 21:47 353
		switch (background_scale_mode) {
727f4a09 Poul Sander 2026-05-24 21:47 354
			case 0: current_background.background_scale = ImgScale::Stretch; break;
727f4a09 Poul Sander 2026-05-24 21:47 355
			case 1: current_background.background_scale = ImgScale::Tile; break;
727f4a09 Poul Sander 2026-05-24 21:47 356
			case 2: current_background.background_scale = ImgScale::Resize; break;
727f4a09 Poul Sander 2026-05-24 21:47 357
			case 3: current_background.background_scale = ImgScale::Cut; break;
727f4a09 Poul Sander 2026-05-24 21:47 358
		}
727f4a09 Poul Sander 2026-05-24 21:47 359
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 360
	}
727f4a09 Poul Sander 2026-05-24 21:47 361
727f4a09 Poul Sander 2026-05-24 21:47 362
	// Tile animation speed
727f4a09 Poul Sander 2026-05-24 21:47 363
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 364
	ImGui::Text("Tile Animation (0 = disabled):");
727f4a09 Poul Sander 2026-05-24 21:47 365
	if (ImGui::DragInt("Move Speed X (ms)", &tile_move_speed_x, 1.0f, 0, 10000)) {
727f4a09 Poul Sander 2026-05-24 21:47 366
		current_background.tileMoveSpeedX = tile_move_speed_x;
727f4a09 Poul Sander 2026-05-24 21:47 367
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 368
	}
727f4a09 Poul Sander 2026-05-24 21:47 369
	if (ImGui::DragInt("Move Speed Y (ms)", &tile_move_speed_y, 1.0f, 0, 10000)) {
727f4a09 Poul Sander 2026-05-24 21:47 370
		current_background.tileMoveSpeedY = tile_move_speed_y;
727f4a09 Poul Sander 2026-05-24 21:47 371
		preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 372
	}
727f4a09 Poul Sander 2026-05-24 21:47 373
727f4a09 Poul Sander 2026-05-24 21:47 374
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 375
	if (ImGui::Button("Save Background")) {
727f4a09 Poul Sander 2026-05-24 21:47 376
		SaveCurrentBackground();
727f4a09 Poul Sander 2026-05-24 21:47 377
	}
727f4a09 Poul Sander 2026-05-24 21:47 378
	ImGui::SameLine();
727f4a09 Poul Sander 2026-05-24 21:47 379
	ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Saved to: backgrounds/<name>.json");
727f4a09 Poul Sander 2026-05-24 21:47 380
}
727f4a09 Poul Sander 2026-05-24 21:47 381
727f4a09 Poul Sander 2026-05-24 21:47 382
void ThemeEditorState::DrawThemeComposer() {
727f4a09 Poul Sander 2026-05-24 21:47 383
	ImGui::Text("Combine borders and backgrounds into a complete theme");
727f4a09 Poul Sander 2026-05-24 21:47 384
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 385
727f4a09 Poul Sander 2026-05-24 21:47 386
	// Theme name
727f4a09 Poul Sander 2026-05-24 21:47 387
	ImGui::InputText("Theme Name", theme_name_buffer, sizeof(theme_name_buffer));
727f4a09 Poul Sander 2026-05-24 21:47 388
727f4a09 Poul Sander 2026-05-24 21:47 389
	// Border selection
727f4a09 Poul Sander 2026-05-24 21:47 390
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 391
	ImGui::Text("Select Border:");
727f4a09 Poul Sander 2026-05-24 21:47 392
	if (ImGui::BeginCombo("##BorderSelect", static_cast<size_t>(selected_border_index) < border_names.size() ? border_names[selected_border_index].c_str() : "")) {
727f4a09 Poul Sander 2026-05-24 21:47 393
		for (size_t i = 0; i < border_names.size(); i++) {
727f4a09 Poul Sander 2026-05-24 21:47 394
			bool is_selected = (static_cast<size_t>(selected_border_index) == i);
727f4a09 Poul Sander 2026-05-24 21:47 395
			if (ImGui::Selectable(border_names[i].c_str(), is_selected)) {
727f4a09 Poul Sander 2026-05-24 21:47 396
				selected_border_index = i;
727f4a09 Poul Sander 2026-05-24 21:47 397
				preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 398
			}
727f4a09 Poul Sander 2026-05-24 21:47 399
			if (is_selected) {
727f4a09 Poul Sander 2026-05-24 21:47 400
				ImGui::SetItemDefaultFocus();
727f4a09 Poul Sander 2026-05-24 21:47 401
			}
727f4a09 Poul Sander 2026-05-24 21:47 402
		}
727f4a09 Poul Sander 2026-05-24 21:47 403
		ImGui::EndCombo();
727f4a09 Poul Sander 2026-05-24 21:47 404
	}
727f4a09 Poul Sander 2026-05-24 21:47 405
727f4a09 Poul Sander 2026-05-24 21:47 406
	// Background selection
727f4a09 Poul Sander 2026-05-24 21:47 407
	ImGui::Text("Select Background:");
727f4a09 Poul Sander 2026-05-24 21:47 408
	if (ImGui::BeginCombo("##BackgroundSelect", static_cast<size_t>(selected_background_index) < background_names.size() ? background_names[selected_background_index].c_str() : "")) {
727f4a09 Poul Sander 2026-05-24 21:47 409
		for (size_t i = 0; i < background_names.size(); i++) {
727f4a09 Poul Sander 2026-05-24 21:47 410
			bool is_selected = (static_cast<size_t>(selected_background_index) == i);
727f4a09 Poul Sander 2026-05-24 21:47 411
			if (ImGui::Selectable(background_names[i].c_str(), is_selected)) {
727f4a09 Poul Sander 2026-05-24 21:47 412
				selected_background_index = i;
727f4a09 Poul Sander 2026-05-24 21:47 413
				preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 414
			}
727f4a09 Poul Sander 2026-05-24 21:47 415
			if (is_selected) {
727f4a09 Poul Sander 2026-05-24 21:47 416
				ImGui::SetItemDefaultFocus();
727f4a09 Poul Sander 2026-05-24 21:47 417
			}
727f4a09 Poul Sander 2026-05-24 21:47 418
		}
727f4a09 Poul Sander 2026-05-24 21:47 419
		ImGui::EndCombo();
727f4a09 Poul Sander 2026-05-24 21:47 420
	}
727f4a09 Poul Sander 2026-05-24 21:47 421
727f4a09 Poul Sander 2026-05-24 21:47 422
	// Decoration selection
727f4a09 Poul Sander 2026-05-24 21:47 423
	ImGui::Text("Select Decoration:");
727f4a09 Poul Sander 2026-05-24 21:47 424
	if (ImGui::BeginCombo("##DecorationSelect", static_cast<size_t>(selected_decoration_index) < decoration_names.size() ? decoration_names[selected_decoration_index].c_str() : "")) {
727f4a09 Poul Sander 2026-05-24 21:47 425
		for (size_t i = 0; i < decoration_names.size(); i++) {
727f4a09 Poul Sander 2026-05-24 21:47 426
			bool is_selected = (static_cast<size_t>(selected_decoration_index) == i);
727f4a09 Poul Sander 2026-05-24 21:47 427
			if (ImGui::Selectable(decoration_names[i].c_str(), is_selected)) {
727f4a09 Poul Sander 2026-05-24 21:47 428
				selected_decoration_index = i;
727f4a09 Poul Sander 2026-05-24 21:47 429
				preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 430
			}
727f4a09 Poul Sander 2026-05-24 21:47 431
			if (is_selected) {
727f4a09 Poul Sander 2026-05-24 21:47 432
				ImGui::SetItemDefaultFocus();
727f4a09 Poul Sander 2026-05-24 21:47 433
			}
727f4a09 Poul Sander 2026-05-24 21:47 434
		}
727f4a09 Poul Sander 2026-05-24 21:47 435
		ImGui::EndCombo();
727f4a09 Poul Sander 2026-05-24 21:47 436
	}
727f4a09 Poul Sander 2026-05-24 21:47 437
727f4a09 Poul Sander 2026-05-24 21:47 438
	// Board background selection
727f4a09 Poul Sander 2026-05-24 21:47 439
	ImGui::Text("Select Board Background:");
727f4a09 Poul Sander 2026-05-24 21:47 440
	if (ImGui::BeginCombo("##BoardBGSelect", board_backgrounds[selected_board_background].c_str())) {
727f4a09 Poul Sander 2026-05-24 21:47 441
		for (size_t i = 0; i < board_backgrounds.size(); i++) {
727f4a09 Poul Sander 2026-05-24 21:47 442
			bool is_selected = (static_cast<size_t>(selected_board_background) == i);
727f4a09 Poul Sander 2026-05-24 21:47 443
			if (ImGui::Selectable(board_backgrounds[i].c_str(), is_selected)) {
727f4a09 Poul Sander 2026-05-24 21:47 444
				selected_board_background = i;
727f4a09 Poul Sander 2026-05-24 21:47 445
				preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 446
			}
727f4a09 Poul Sander 2026-05-24 21:47 447
			if (is_selected) {
727f4a09 Poul Sander 2026-05-24 21:47 448
				ImGui::SetItemDefaultFocus();
727f4a09 Poul Sander 2026-05-24 21:47 449
			}
727f4a09 Poul Sander 2026-05-24 21:47 450
		}
727f4a09 Poul Sander 2026-05-24 21:47 451
		ImGui::EndCombo();
727f4a09 Poul Sander 2026-05-24 21:47 452
	}
727f4a09 Poul Sander 2026-05-24 21:47 453
727f4a09 Poul Sander 2026-05-24 21:47 454
	ImGui::Separator();
727f4a09 Poul Sander 2026-05-24 21:47 455
	if (ImGui::Button("Save Theme")) {
727f4a09 Poul Sander 2026-05-24 21:47 456
		SaveCurrentTheme();
727f4a09 Poul Sander 2026-05-24 21:47 457
	}
727f4a09 Poul Sander 2026-05-24 21:47 458
	ImGui::SameLine();
727f4a09 Poul Sander 2026-05-24 21:47 459
	ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Saved to: custom_themes.json");
727f4a09 Poul Sander 2026-05-24 21:47 460
}
727f4a09 Poul Sander 2026-05-24 21:47 461
727f4a09 Poul Sander 2026-05-24 21:47 462
void ThemeEditorState::DrawPreview(SDL_Renderer* target) {
727f4a09 Poul Sander 2026-05-24 21:47 463
	(void)target;
727f4a09 Poul Sander 2026-05-24 21:47 464
	// TODO: Implement preview rendering using BlockGameSdl
727f4a09 Poul Sander 2026-05-24 21:47 465
}
727f4a09 Poul Sander 2026-05-24 21:47 466
727f4a09 Poul Sander 2026-05-24 21:47 467
void ThemeEditorState::SaveCurrentBorder() {
727f4a09 Poul Sander 2026-05-24 21:47 468
	// Update current_border from UI fields
727f4a09 Poul Sander 2026-05-24 21:47 469
	std::string name = border_name_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 470
	if (name.empty()) {
727f4a09 Poul Sander 2026-05-24 21:47 471
		std::cerr << "Error: Border name cannot be empty\n";
727f4a09 Poul Sander 2026-05-24 21:47 472
		return;
727f4a09 Poul Sander 2026-05-24 21:47 473
	}
727f4a09 Poul Sander 2026-05-24 21:47 474
727f4a09 Poul Sander 2026-05-24 21:47 475
	current_border.name = name;
727f4a09 Poul Sander 2026-05-24 21:47 476
	current_border.border_sprite = border_sprite_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 477
	current_border.border_sprite_offset = {border_offset_x, border_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 478
	current_border.score_label_offset = {score_offset_x, score_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 479
	current_border.time_label_offset = {time_offset_x, time_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 480
	current_border.chain_label_offset = {chain_offset_x, chain_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 481
	current_border.speed_label_offset = {speed_offset_x, speed_offset_y};
727f4a09 Poul Sander 2026-05-24 21:47 482
	current_border.score_field_offset = {score_field_x, score_field_y};
727f4a09 Poul Sander 2026-05-24 21:47 483
	current_border.time_field_offset = {time_field_x, time_field_y};
727f4a09 Poul Sander 2026-05-24 21:47 484
	current_border.chain_field_offset = {chain_field_x, chain_field_y};
727f4a09 Poul Sander 2026-05-24 21:47 485
	current_border.speed_field_offset = {speed_field_x, speed_field_y};
727f4a09 Poul Sander 2026-05-24 21:47 486
727f4a09 Poul Sander 2026-05-24 21:47 487
	// Validate sprite
727f4a09 Poul Sander 2026-05-24 21:47 488
	if (!ValidateSprite(current_border.border_sprite)) {
727f4a09 Poul Sander 2026-05-24 21:47 489
		std::cerr << "Warning: Saving border with non-existent sprite: " << current_border.border_sprite << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 490
	}
727f4a09 Poul Sander 2026-05-24 21:47 491
727f4a09 Poul Sander 2026-05-24 21:47 492
	// Save to file
727f4a09 Poul Sander 2026-05-24 21:47 493
	ThemesSaveBorderData(name, current_border);
727f4a09 Poul Sander 2026-05-24 21:47 494
	std::cout << "Saved border: " << name << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 495
727f4a09 Poul Sander 2026-05-24 21:47 496
	// Refresh border list
727f4a09 Poul Sander 2026-05-24 21:47 497
	border_names = ThemesGetBorderNames();
727f4a09 Poul Sander 2026-05-24 21:47 498
}
727f4a09 Poul Sander 2026-05-24 21:47 499
727f4a09 Poul Sander 2026-05-24 21:47 500
void ThemeEditorState::SaveCurrentBackground() {
727f4a09 Poul Sander 2026-05-24 21:47 501
	// Update current_background from UI fields
727f4a09 Poul Sander 2026-05-24 21:47 502
	std::string name = background_name_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 503
	if (name.empty()) {
727f4a09 Poul Sander 2026-05-24 21:47 504
		std::cerr << "Error: Background name cannot be empty\n";
727f4a09 Poul Sander 2026-05-24 21:47 505
		return;
727f4a09 Poul Sander 2026-05-24 21:47 506
	}
727f4a09 Poul Sander 2026-05-24 21:47 507
727f4a09 Poul Sander 2026-05-24 21:47 508
	current_background.name = name;
727f4a09 Poul Sander 2026-05-24 21:47 509
	current_background.background_sprite = background_sprite_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 510
	current_background.background_sprite_16x9 = background_sprite_16x9_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 511
727f4a09 Poul Sander 2026-05-24 21:47 512
	// Convert scale mode
727f4a09 Poul Sander 2026-05-24 21:47 513
	switch (background_scale_mode) {
727f4a09 Poul Sander 2026-05-24 21:47 514
		case 0: current_background.background_scale = ImgScale::Stretch; break;
727f4a09 Poul Sander 2026-05-24 21:47 515
		case 1: current_background.background_scale = ImgScale::Tile; break;
727f4a09 Poul Sander 2026-05-24 21:47 516
		case 2: current_background.background_scale = ImgScale::Resize; break;
727f4a09 Poul Sander 2026-05-24 21:47 517
		case 3: current_background.background_scale = ImgScale::Cut; break;
727f4a09 Poul Sander 2026-05-24 21:47 518
	}
727f4a09 Poul Sander 2026-05-24 21:47 519
727f4a09 Poul Sander 2026-05-24 21:47 520
	current_background.tileMoveSpeedX = tile_move_speed_x;
727f4a09 Poul Sander 2026-05-24 21:47 521
	current_background.tileMoveSpeedY = tile_move_speed_y;
727f4a09 Poul Sander 2026-05-24 21:47 522
727f4a09 Poul Sander 2026-05-24 21:47 523
	// Validate sprite
727f4a09 Poul Sander 2026-05-24 21:47 524
	if (!ValidateSprite(current_background.background_sprite)) {
727f4a09 Poul Sander 2026-05-24 21:47 525
		std::cerr << "Warning: Saving background with non-existent sprite: " << current_background.background_sprite << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 526
	}
727f4a09 Poul Sander 2026-05-24 21:47 527
727f4a09 Poul Sander 2026-05-24 21:47 528
	// Save to file
727f4a09 Poul Sander 2026-05-24 21:47 529
	ThemesSaveBackgroundData(name, current_background);
727f4a09 Poul Sander 2026-05-24 21:47 530
	std::cout << "Saved background: " << name << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 531
727f4a09 Poul Sander 2026-05-24 21:47 532
	// Refresh background list
727f4a09 Poul Sander 2026-05-24 21:47 533
	background_names = ThemesGetBackgroundNames();
727f4a09 Poul Sander 2026-05-24 21:47 534
}
727f4a09 Poul Sander 2026-05-24 21:47 535
727f4a09 Poul Sander 2026-05-24 21:47 536
void ThemeEditorState::SaveCurrentTheme() {
727f4a09 Poul Sander 2026-05-24 21:47 537
	std::string name = theme_name_buffer;
727f4a09 Poul Sander 2026-05-24 21:47 538
	if (name.empty()) {
727f4a09 Poul Sander 2026-05-24 21:47 539
		std::cerr << "Error: Theme name cannot be empty\n";
727f4a09 Poul Sander 2026-05-24 21:47 540
		return;
727f4a09 Poul Sander 2026-05-24 21:47 541
	}
727f4a09 Poul Sander 2026-05-24 21:47 542
727f4a09 Poul Sander 2026-05-24 21:47 543
	Theme theme;
727f4a09 Poul Sander 2026-05-24 21:47 544
	theme.theme_name = name;
727f4a09 Poul Sander 2026-05-24 21:47 545
727f4a09 Poul Sander 2026-05-24 21:47 546
	// Set components
727f4a09 Poul Sander 2026-05-24 21:47 547
	if (static_cast<size_t>(selected_border_index) < border_names.size()) {
727f4a09 Poul Sander 2026-05-24 21:47 548
		theme.border = ThemesGetBorder(border_names[selected_border_index]);
727f4a09 Poul Sander 2026-05-24 21:47 549
	}
727f4a09 Poul Sander 2026-05-24 21:47 550
	if (static_cast<size_t>(selected_background_index) < background_names.size()) {
727f4a09 Poul Sander 2026-05-24 21:47 551
		theme.background = ThemesGetBackground(background_names[selected_background_index]);
727f4a09 Poul Sander 2026-05-24 21:47 552
	}
727f4a09 Poul Sander 2026-05-24 21:47 553
	theme.back_board = board_backgrounds[selected_board_background];
727f4a09 Poul Sander 2026-05-24 21:47 554
727f4a09 Poul Sander 2026-05-24 21:47 555
	// Add or replace the theme
727f4a09 Poul Sander 2026-05-24 21:47 556
	ThemesAddOrReplace(theme);
727f4a09 Poul Sander 2026-05-24 21:47 557
727f4a09 Poul Sander 2026-05-24 21:47 558
	// Save to custom themes file
727f4a09 Poul Sander 2026-05-24 21:47 559
	ThemesSaveCustomSlots();
727f4a09 Poul Sander 2026-05-24 21:47 560
727f4a09 Poul Sander 2026-05-24 21:47 561
	std::cout << "Saved theme: " << name << "\n";
727f4a09 Poul Sander 2026-05-24 21:47 562
}
727f4a09 Poul Sander 2026-05-24 21:47 563
727f4a09 Poul Sander 2026-05-24 21:47 564
void ThemeEditorState::LoadBorder(const std::string& name) {
727f4a09 Poul Sander 2026-05-24 21:47 565
	current_border = ThemesGetBorder(name);
727f4a09 Poul Sander 2026-05-24 21:47 566
727f4a09 Poul Sander 2026-05-24 21:47 567
	// Update UI fields
727f4a09 Poul Sander 2026-05-24 21:47 568
	strncpy(border_name_buffer, current_border.name.c_str(), sizeof(border_name_buffer) - 1);
727f4a09 Poul Sander 2026-05-24 21:47 569
	strncpy(border_sprite_buffer, current_border.border_sprite.c_str(), sizeof(border_sprite_buffer) - 1);
727f4a09 Poul Sander 2026-05-24 21:47 570
	border_offset_x = current_border.border_sprite_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 571
	border_offset_y = current_border.border_sprite_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 572
	score_offset_x = current_border.score_label_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 573
	score_offset_y = current_border.score_label_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 574
	time_offset_x = current_border.time_label_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 575
	time_offset_y = current_border.time_label_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 576
	chain_offset_x = current_border.chain_label_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 577
	chain_offset_y = current_border.chain_label_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 578
	speed_offset_x = current_border.speed_label_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 579
	speed_offset_y = current_border.speed_label_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 580
	score_field_x = current_border.score_field_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 581
	score_field_y = current_border.score_field_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 582
	time_field_x = current_border.time_field_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 583
	time_field_y = current_border.time_field_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 584
	chain_field_x = current_border.chain_field_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 585
	chain_field_y = current_border.chain_field_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 586
	speed_field_x = current_border.speed_field_offset.first;
727f4a09 Poul Sander 2026-05-24 21:47 587
	speed_field_y = current_border.speed_field_offset.second;
727f4a09 Poul Sander 2026-05-24 21:47 588
	preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 589
}
727f4a09 Poul Sander 2026-05-24 21:47 590
727f4a09 Poul Sander 2026-05-24 21:47 591
void ThemeEditorState::LoadBackground(const std::string& name) {
727f4a09 Poul Sander 2026-05-24 21:47 592
	current_background = ThemesGetBackground(name);
727f4a09 Poul Sander 2026-05-24 21:47 593
727f4a09 Poul Sander 2026-05-24 21:47 594
	// Update UI fields
727f4a09 Poul Sander 2026-05-24 21:47 595
	strncpy(background_name_buffer, current_background.name.c_str(), sizeof(background_name_buffer) - 1);
727f4a09 Poul Sander 2026-05-24 21:47 596
	strncpy(background_sprite_buffer, current_background.background_sprite.c_str(), sizeof(background_sprite_buffer) - 1);
727f4a09 Poul Sander 2026-05-24 21:47 597
	strncpy(background_sprite_16x9_buffer, current_background.background_sprite_16x9.c_str(), sizeof(background_sprite_16x9_buffer) - 1);
727f4a09 Poul Sander 2026-05-24 21:47 598
727f4a09 Poul Sander 2026-05-24 21:47 599
	// Convert scale mode
727f4a09 Poul Sander 2026-05-24 21:47 600
	switch (current_background.background_scale) {
727f4a09 Poul Sander 2026-05-24 21:47 601
		case ImgScale::Stretch: background_scale_mode = 0; break;
727f4a09 Poul Sander 2026-05-24 21:47 602
		case ImgScale::Tile: background_scale_mode = 1; break;
727f4a09 Poul Sander 2026-05-24 21:47 603
		case ImgScale::Resize: background_scale_mode = 2; break;
727f4a09 Poul Sander 2026-05-24 21:47 604
		case ImgScale::Cut: background_scale_mode = 3; break;
727f4a09 Poul Sander 2026-05-24 21:47 605
	}
727f4a09 Poul Sander 2026-05-24 21:47 606
727f4a09 Poul Sander 2026-05-24 21:47 607
	tile_move_speed_x = current_background.tileMoveSpeedX;
727f4a09 Poul Sander 2026-05-24 21:47 608
	tile_move_speed_y = current_background.tileMoveSpeedY;
727f4a09 Poul Sander 2026-05-24 21:47 609
	preview_needs_update = true;
727f4a09 Poul Sander 2026-05-24 21:47 610
}
727f4a09 Poul Sander 2026-05-24 21:47 611
727f4a09 Poul Sander 2026-05-24 21:47 612
bool ThemeEditorState::ValidateSprite(const std::string& sprite_name) {
727f4a09 Poul Sander 2026-05-24 21:47 613
	return ThemesValidateSpriteName(sprite_name);
727f4a09 Poul Sander 2026-05-24 21:47 614
}
727f4a09 Poul Sander 2026-05-24 21:47 615
727f4a09 Poul Sander 2026-05-24 21:47 616
std::vector<std::string> ThemeEditorState::GetAvailableSprites() {
727f4a09 Poul Sander 2026-05-24 21:47 617
	// TODO: Implement getting available sprite names from globalData.spriteHolder
727f4a09 Poul Sander 2026-05-24 21:47 618
	return std::vector<std::string>();
727f4a09 Poul Sander 2026-05-24 21:47 619
}
1970-01-01 00:00 620