git repos / blockattack-game

blame: source/code/puzzle_editor/PuzzleEditorState.cpp

normal view · raw

1873b078 Poul Sander 2025-02-06 22:01 1
/*
1873b078 Poul Sander 2025-02-06 22:01 2
===========================================================================
1873b078 Poul Sander 2025-02-06 22:01 3
blockattack - Block Attack - Rise of the Blocks
1873b078 Poul Sander 2025-02-06 22:01 4
Copyright (C) 2005-2025 Poul Sander
1873b078 Poul Sander 2025-02-06 22:01 5
1873b078 Poul Sander 2025-02-06 22:01 6
This program is free software: you can redistribute it and/or modify
1873b078 Poul Sander 2025-02-06 22:01 7
it under the terms of the GNU General Public License as published by
1873b078 Poul Sander 2025-02-06 22:01 8
the Free Software Foundation, either version 2 of the License, or
1873b078 Poul Sander 2025-02-06 22:01 9
(at your option) any later version.
1873b078 Poul Sander 2025-02-06 22:01 10
1873b078 Poul Sander 2025-02-06 22:01 11
This program is distributed in the hope that it will be useful,
1873b078 Poul Sander 2025-02-06 22:01 12
but WITHOUT ANY WARRANTY; without even the implied warranty of
1873b078 Poul Sander 2025-02-06 22:01 13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1873b078 Poul Sander 2025-02-06 22:01 14
GNU General Public License for more details.
1873b078 Poul Sander 2025-02-06 22:01 15
1873b078 Poul Sander 2025-02-06 22:01 16
You should have received a copy of the GNU General Public License
1873b078 Poul Sander 2025-02-06 22:01 17
along with this program.  If not, see http://www.gnu.org/licenses/
1873b078 Poul Sander 2025-02-06 22:01 18
1873b078 Poul Sander 2025-02-06 22:01 19
Source information and contacts persons can be found at
1873b078 Poul Sander 2025-02-06 22:01 20
https://blockattack.net
1873b078 Poul Sander 2025-02-06 22:01 21
===========================================================================
1873b078 Poul Sander 2025-02-06 22:01 22
*/
1873b078 Poul Sander 2025-02-06 22:01 23
1873b078 Poul Sander 2025-02-06 22:01 24
#include "PuzzleEditorState.hpp"
298835a8 Poul Sander 2025-05-31 20:49 25
298835a8 Poul Sander 2025-05-31 20:49 26
#include <unistd.h>
52352a94 Poul Sander 2025-06-03 19:04 27
#include <fmt/core.h>
298835a8 Poul Sander 2025-05-31 20:49 28
1873b078 Poul Sander 2025-02-06 22:01 29
#include "imgui.h"
37278577 Poul Sander 2025-06-21 07:50 30
#include "imgui_internal.h"
1873b078 Poul Sander 2025-02-06 22:01 31
#include "backends/imgui_impl_sdl2.h"
1873b078 Poul Sander 2025-02-06 22:01 32
#include "backends/imgui_impl_sdlrenderer2.h"
a80f6a78 Poul Sander 2025-04-04 18:34 33
#include "../sago/SagoMisc.hpp"
a80f6a78 Poul Sander 2025-04-04 18:34 34
#include "../puzzlehandler.hpp"
1873b078 Poul Sander 2025-02-06 22:01 35
1873b078 Poul Sander 2025-02-06 22:01 36
af6d5a44 Poul Sander 2025-06-21 19:31 37
void SetSinglePuzzleMode(int level);
af6d5a44 Poul Sander 2025-06-21 19:31 38
636cde3b Poul Sander 2025-05-15 21:40 39
PuzzleEditorState::PuzzleEditorState() {
636cde3b Poul Sander 2025-05-15 21:40 40
	this->window_resize = sago::SagoLogicalResize(BOARD_WIDTH+5, BOARD_HEIGHT+5);
636cde3b Poul Sander 2025-05-15 21:40 41
}
636cde3b Poul Sander 2025-05-15 21:40 42
1873b078 Poul Sander 2025-02-06 22:01 43
bool PuzzleEditorState::IsActive() {
1873b078 Poul Sander 2025-02-06 22:01 44
	return isActive;
1873b078 Poul Sander 2025-02-06 22:01 45
}
1873b078 Poul Sander 2025-02-06 22:01 46
1873b078 Poul Sander 2025-02-06 22:01 47
void PuzzleEditorState::ProcessInput(const SDL_Event& event, bool& processed) {
4ebb3d36 Poul Sander 2025-10-05 11:55 48
	if (event.type == SDL_KEYDOWN && !read_only) {
ee1c1ede Poul Sander 2025-10-07 19:28 49
		const Uint8* keystate = SDL_GetKeyboardState(nullptr);
ee1c1ede Poul Sander 2025-10-07 19:28 50
		const bool ctrl_held = keystate[SDL_SCANCODE_LCTRL] || keystate[SDL_SCANCODE_RCTRL];
4ebb3d36 Poul Sander 2025-10-05 11:55 51
4ebb3d36 Poul Sander 2025-10-05 11:55 52
		if (ctrl_held && event.key.keysym.sym == SDLK_z) {
4ebb3d36 Poul Sander 2025-10-05 11:55 53
			if (keystate[SDL_SCANCODE_LSHIFT] || keystate[SDL_SCANCODE_RSHIFT]) {
4ebb3d36 Poul Sander 2025-10-05 11:55 54
				Redo();
4ebb3d36 Poul Sander 2025-10-05 11:55 55
			} else {
4ebb3d36 Poul Sander 2025-10-05 11:55 56
				Undo();
4ebb3d36 Poul Sander 2025-10-05 11:55 57
			}
4ebb3d36 Poul Sander 2025-10-05 11:55 58
			processed = true;
4ebb3d36 Poul Sander 2025-10-05 11:55 59
		} else if (ctrl_held && event.key.keysym.sym == SDLK_y) {
4ebb3d36 Poul Sander 2025-10-05 11:55 60
			Redo();
4ebb3d36 Poul Sander 2025-10-05 11:55 61
			processed = true;
4ebb3d36 Poul Sander 2025-10-05 11:55 62
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 63
	}
1873b078 Poul Sander 2025-02-06 22:01 64
}
1873b078 Poul Sander 2025-02-06 22:01 65
a80f6a78 Poul Sander 2025-04-04 18:34 66
void PuzzleEditorState::Init() {
a80f6a78 Poul Sander 2025-04-04 18:34 67
	this->selected_file = "";
a80f6a78 Poul Sander 2025-04-04 18:34 68
	this->puzzle_files = sago::GetFileList("puzzles");
a80f6a78 Poul Sander 2025-04-04 18:34 69
}
a80f6a78 Poul Sander 2025-04-04 18:34 70
a80f6a78 Poul Sander 2025-04-04 18:34 71
void PuzzleEditorState::SelectFile(const std::string& file) {
4ebb3d36 Poul Sander 2025-10-05 11:55 72
	undo_file_stack[this->selected_file] = undo_stack;
4ebb3d36 Poul Sander 2025-10-05 11:55 73
	redo_file_stack[this->selected_file] = redo_stack;
a80f6a78 Poul Sander 2025-04-04 18:34 74
	this->selected_file = file;
a80f6a78 Poul Sander 2025-04-04 18:34 75
	PuzzleSetName(file);
a80f6a78 Poul Sander 2025-04-04 18:34 76
	LoadPuzzleStages();
298835a8 Poul Sander 2025-05-31 20:49 77
	read_only = false;
4ebb3d36 Poul Sander 2025-10-05 11:55 78
	undo_stack = undo_file_stack[this->selected_file];
4ebb3d36 Poul Sander 2025-10-05 11:55 79
	redo_stack = redo_file_stack[this->selected_file];
298835a8 Poul Sander 2025-05-31 20:49 80
	if (file == "puzzle.levels") {
298835a8 Poul Sander 2025-05-31 20:49 81
		read_only = true;
298835a8 Poul Sander 2025-05-31 20:49 82
	}
a80f6a78 Poul Sander 2025-04-04 18:34 83
}
a80f6a78 Poul Sander 2025-04-04 18:34 84
636cde3b Poul Sander 2025-05-15 21:40 85
static void LogicalToPhysical(const sago::SagoLogicalResize& resize, ImVec2& inout) {
ee1c1ede Poul Sander 2025-10-07 19:28 86
	const int inx = inout.x;
ee1c1ede Poul Sander 2025-10-07 19:28 87
	const int iny = inout.y;
ee1c1ede Poul Sander 2025-10-07 19:28 88
	int out_x = inout.x;
ee1c1ede Poul Sander 2025-10-07 19:28 89
	int out_y = inout.y;
ee1c1ede Poul Sander 2025-10-07 19:28 90
	resize.LogicalToPhysical(inx, iny, out_x, out_y);
ee1c1ede Poul Sander 2025-10-07 19:28 91
	inout.x = out_x;
ee1c1ede Poul Sander 2025-10-07 19:28 92
	inout.y = out_y;
636cde3b Poul Sander 2025-05-15 21:40 93
}
636cde3b Poul Sander 2025-05-15 21:40 94
59365d69 Poul Sander 2025-05-25 12:06 95
e1a54754 Poul Sander 2025-05-25 13:31 96
static void ImGuiWritePartOfTexture(SDL_Texture* texture, int topx, int topy, int tex_w, int tex_h, int w, int h) {
ee1c1ede Poul Sander 2025-10-07 19:28 97
	const float sprite_w = tex_w;
ee1c1ede Poul Sander 2025-10-07 19:28 98
	const float sprite_h = tex_h;
ee1c1ede Poul Sander 2025-10-07 19:28 99
	const float top_x_f = topx;
ee1c1ede Poul Sander 2025-10-07 19:28 100
	const float top_y_f = topy;
ee1c1ede Poul Sander 2025-10-07 19:28 101
	const ImVec2 uv0 = ImVec2(top_x_f / tex_w, top_y_f / tex_h);
ee1c1ede Poul Sander 2025-10-07 19:28 102
	const ImVec2 uv1 = ImVec2((top_x_f + sprite_w) / tex_w, (top_y_f + sprite_h) / tex_h);
59365d69 Poul Sander 2025-05-25 12:06 103
	ImGui::Image((ImTextureID)(intptr_t)texture, ImVec2((float)w, (float)h), uv0, uv1);
59365d69 Poul Sander 2025-05-25 12:06 104
}
59365d69 Poul Sander 2025-05-25 12:06 105
59365d69 Poul Sander 2025-05-25 12:06 106
59365d69 Poul Sander 2025-05-25 12:06 107
static void DrawBrick(int brick, int x, int y, int width, int height) {
59365d69 Poul Sander 2025-05-25 12:06 108
	if (brick < 0 || brick > 6) {
59365d69 Poul Sander 2025-05-25 12:06 109
		return;
59365d69 Poul Sander 2025-05-25 12:06 110
	}
59365d69 Poul Sander 2025-05-25 12:06 111
59365d69 Poul Sander 2025-05-25 12:06 112
	sago::SagoSprite& sprite = globalData.bricks[brick];
59365d69 Poul Sander 2025-05-25 12:06 113
	ImGui::SetCursorScreenPos({ static_cast<float>(x), static_cast<float>(y) });
1ae9f202 Poul Sander 2025-05-30 13:59 114
	ImGuiWritePartOfTexture(sprite.GetTextureHandler().get(), sprite.GetImageCord().x, sprite.GetImageCord().y, sprite.GetWidth(), sprite.GetHeight(), width, height);
59365d69 Poul Sander 2025-05-25 12:06 115
}
59365d69 Poul Sander 2025-05-25 12:06 116
72e87270 Poul Sander 2025-06-21 15:22 117
/**
72e87270 Poul Sander 2025-06-21 15:22 118
 * Takes the brick pointed to and moves up all bricks above it to leave an empty space.
72e87270 Poul Sander 2025-06-21 15:22 119
 * If bricks are pushed out of the board then the disappear.
72e87270 Poul Sander 2025-06-21 15:22 120
 * @param level The level to edit
72e87270 Poul Sander 2025-06-21 15:22 121
 * @param x
72e87270 Poul Sander 2025-06-21 15:22 122
 * @param y
72e87270 Poul Sander 2025-06-21 15:22 123
 */
72e87270 Poul Sander 2025-06-21 15:22 124
static void BricksMoveUp(int level, int x, int y) {
72e87270 Poul Sander 2025-06-21 15:22 125
	for (int i = 11; i > y; i--) {
72e87270 Poul Sander 2025-06-21 15:22 126
		PuzzleSetBrick(level, x, i, PuzzleGetBrick(level, x, i-1));
72e87270 Poul Sander 2025-06-21 15:22 127
	}
72e87270 Poul Sander 2025-06-21 15:22 128
	PuzzleSetBrick(level, x, y, -1);  //Clear the space we started
72e87270 Poul Sander 2025-06-21 15:22 129
}
72e87270 Poul Sander 2025-06-21 15:22 130
72e87270 Poul Sander 2025-06-21 15:22 131
static void BricksMoveDown(int level, int x, int y) {
72e87270 Poul Sander 2025-06-21 15:22 132
	for (int i = 0; i < y; i++) {
72e87270 Poul Sander 2025-06-21 15:22 133
		PuzzleSetBrick(level, x, i, PuzzleGetBrick(level, x, i+1));
72e87270 Poul Sander 2025-06-21 15:22 134
	}
72e87270 Poul Sander 2025-06-21 15:22 135
	PuzzleSetBrick(level, x, y, -1);  //Clear the space we started
72e87270 Poul Sander 2025-06-21 15:22 136
}
72e87270 Poul Sander 2025-06-21 15:22 137
72e87270 Poul Sander 2025-06-21 15:22 138
static void BricksMoveColumnLeft(int level, int x) {
72e87270 Poul Sander 2025-06-21 15:22 139
	for (int i=0; i < x; i++) {
72e87270 Poul Sander 2025-06-21 15:22 140
		for (int j=0; j<12 ; j++) {
72e87270 Poul Sander 2025-06-21 15:22 141
			PuzzleSetBrick(level, i, j, PuzzleGetBrick(level, i+1, j));
72e87270 Poul Sander 2025-06-21 15:22 142
		}
72e87270 Poul Sander 2025-06-21 15:22 143
	}
72e87270 Poul Sander 2025-06-21 15:22 144
	for (int j=0; j<12 ; j++) {
72e87270 Poul Sander 2025-06-21 15:22 145
		PuzzleSetBrick(level, x, j, -1);
72e87270 Poul Sander 2025-06-21 15:22 146
	}
72e87270 Poul Sander 2025-06-21 15:22 147
}
72e87270 Poul Sander 2025-06-21 15:22 148
72e87270 Poul Sander 2025-06-21 15:22 149
static void BricksMoveColumnRight(int level, int x) {
72e87270 Poul Sander 2025-06-21 15:22 150
	for (int i=5; i > x; i--) {
72e87270 Poul Sander 2025-06-21 15:22 151
		for (int j=0; j<12 ; j++) {
72e87270 Poul Sander 2025-06-21 15:22 152
			PuzzleSetBrick(level, i, j, PuzzleGetBrick(level, i-1, j));
72e87270 Poul Sander 2025-06-21 15:22 153
		}
72e87270 Poul Sander 2025-06-21 15:22 154
	}
72e87270 Poul Sander 2025-06-21 15:22 155
	for (int j=0; j<12 ; j++) {
72e87270 Poul Sander 2025-06-21 15:22 156
		PuzzleSetBrick(level, x, j, -1);
72e87270 Poul Sander 2025-06-21 15:22 157
	}
72e87270 Poul Sander 2025-06-21 15:22 158
}
72e87270 Poul Sander 2025-06-21 15:22 159
b8a4e6f1 Poul Sander 2025-06-21 10:31 160
4ebb3d36 Poul Sander 2025-10-05 11:55 161
void PuzzleEditorState::SaveCurrentState() {
4ebb3d36 Poul Sander 2025-10-05 11:55 162
	if (undo_stack.size() >= MAX_UNDO_STATES) {
4ebb3d36 Poul Sander 2025-10-05 11:55 163
		std::vector<PuzzleState> temp;
4ebb3d36 Poul Sander 2025-10-05 11:55 164
		for (size_t i = 0; i < MAX_UNDO_STATES - 1; ++i) {
4ebb3d36 Poul Sander 2025-10-05 11:55 165
			temp.push_back(undo_stack.back());
4ebb3d36 Poul Sander 2025-10-05 11:55 166
			undo_stack.pop_back();
4ebb3d36 Poul Sander 2025-10-05 11:55 167
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 168
		undo_stack = std::vector<PuzzleState>();
9d84cac6 Poul Sander 2025-10-07 18:43 169
		while (temp.size()) {
4ebb3d36 Poul Sander 2025-10-05 11:55 170
			undo_stack.push_back(temp.back());
4ebb3d36 Poul Sander 2025-10-05 11:55 171
			temp.pop_back();
4ebb3d36 Poul Sander 2025-10-05 11:55 172
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 173
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 174
4ebb3d36 Poul Sander 2025-10-05 11:55 175
	PuzzleState current_state;
4ebb3d36 Poul Sander 2025-10-05 11:55 176
	current_state.puzzle_count = PuzzleGetNumberOfPuzzles();
4ebb3d36 Poul Sander 2025-10-05 11:55 177
	current_state.current_puzzle = this->selected_puzzle;
4ebb3d36 Poul Sander 2025-10-05 11:55 178
	current_state.moves_allowed.resize(current_state.puzzle_count);
4ebb3d36 Poul Sander 2025-10-05 11:55 179
4ebb3d36 Poul Sander 2025-10-05 11:55 180
	for (int level = 0; level < current_state.puzzle_count; ++level) {
4ebb3d36 Poul Sander 2025-10-05 11:55 181
		current_state.moves_allowed[level] = PuzzleNumberOfMovesAllowed(level);
4ebb3d36 Poul Sander 2025-10-05 11:55 182
		for (int x = 0; x < 6; ++x) {
4ebb3d36 Poul Sander 2025-10-05 11:55 183
			for (int y = 0; y < 12; ++y) {
4ebb3d36 Poul Sander 2025-10-05 11:55 184
				current_state.puzzle_data[level][x][y] = PuzzleGetBrick(level, x, y);
4ebb3d36 Poul Sander 2025-10-05 11:55 185
			}
4ebb3d36 Poul Sander 2025-10-05 11:55 186
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 187
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 188
4ebb3d36 Poul Sander 2025-10-05 11:55 189
	undo_stack.push_back(current_state);
9d84cac6 Poul Sander 2025-10-07 18:43 190
	while (redo_stack.size()) {
4ebb3d36 Poul Sander 2025-10-05 11:55 191
		redo_stack.pop_back();
4ebb3d36 Poul Sander 2025-10-05 11:55 192
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 193
}
4ebb3d36 Poul Sander 2025-10-05 11:55 194
4ebb3d36 Poul Sander 2025-10-05 11:55 195
void PuzzleEditorState::Undo() {
4ebb3d36 Poul Sander 2025-10-05 11:55 196
	if (!CanUndo()) {
4ebb3d36 Poul Sander 2025-10-05 11:55 197
		return;
4ebb3d36 Poul Sander 2025-10-05 11:55 198
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 199
4ebb3d36 Poul Sander 2025-10-05 11:55 200
	PuzzleState current_state;
4ebb3d36 Poul Sander 2025-10-05 11:55 201
	current_state.puzzle_count = PuzzleGetNumberOfPuzzles();
4ebb3d36 Poul Sander 2025-10-05 11:55 202
	current_state.current_puzzle = this->selected_puzzle;
4ebb3d36 Poul Sander 2025-10-05 11:55 203
	current_state.moves_allowed.resize(current_state.puzzle_count);
4ebb3d36 Poul Sander 2025-10-05 11:55 204
4ebb3d36 Poul Sander 2025-10-05 11:55 205
	for (int level = 0; level < current_state.puzzle_count; ++level) {
4ebb3d36 Poul Sander 2025-10-05 11:55 206
		current_state.moves_allowed[level] = PuzzleNumberOfMovesAllowed(level);
4ebb3d36 Poul Sander 2025-10-05 11:55 207
		for (int x = 0; x < 6; ++x) {
4ebb3d36 Poul Sander 2025-10-05 11:55 208
			for (int y = 0; y < 12; ++y) {
4ebb3d36 Poul Sander 2025-10-05 11:55 209
				current_state.puzzle_data[level][x][y] = PuzzleGetBrick(level, x, y);
4ebb3d36 Poul Sander 2025-10-05 11:55 210
			}
4ebb3d36 Poul Sander 2025-10-05 11:55 211
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 212
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 213
	redo_stack.push_back(current_state);
4ebb3d36 Poul Sander 2025-10-05 11:55 214
4ebb3d36 Poul Sander 2025-10-05 11:55 215
	PuzzleState previous_state = undo_stack.back();
4ebb3d36 Poul Sander 2025-10-05 11:55 216
	undo_stack.pop_back();
4ebb3d36 Poul Sander 2025-10-05 11:55 217
4ebb3d36 Poul Sander 2025-10-05 11:55 218
	EditorResizePuzzleNumber(previous_state.puzzle_count);
4ebb3d36 Poul Sander 2025-10-05 11:55 219
	for (int level = 0; level < previous_state.puzzle_count; ++level) {
4ebb3d36 Poul Sander 2025-10-05 11:55 220
		PuzzleNumberOfMovesAllowedSet(level, previous_state.moves_allowed[level]);
4ebb3d36 Poul Sander 2025-10-05 11:55 221
		for (int x = 0; x < 6; ++x) {
4ebb3d36 Poul Sander 2025-10-05 11:55 222
			for (int y = 0; y < 12; ++y) {
4ebb3d36 Poul Sander 2025-10-05 11:55 223
				PuzzleSetBrick(level, x, y, previous_state.puzzle_data[level][x][y]);
4ebb3d36 Poul Sander 2025-10-05 11:55 224
			}
4ebb3d36 Poul Sander 2025-10-05 11:55 225
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 226
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 227
4ebb3d36 Poul Sander 2025-10-05 11:55 228
	this->selected_puzzle = previous_state.current_puzzle;
4ebb3d36 Poul Sander 2025-10-05 11:55 229
	SavePuzzleStages();
4ebb3d36 Poul Sander 2025-10-05 11:55 230
}
4ebb3d36 Poul Sander 2025-10-05 11:55 231
4ebb3d36 Poul Sander 2025-10-05 11:55 232
void PuzzleEditorState::Redo() {
4ebb3d36 Poul Sander 2025-10-05 11:55 233
	if (!CanRedo()) {
4ebb3d36 Poul Sander 2025-10-05 11:55 234
		return;
4ebb3d36 Poul Sander 2025-10-05 11:55 235
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 236
4ebb3d36 Poul Sander 2025-10-05 11:55 237
	PuzzleState current_state;
4ebb3d36 Poul Sander 2025-10-05 11:55 238
	current_state.puzzle_count = PuzzleGetNumberOfPuzzles();
4ebb3d36 Poul Sander 2025-10-05 11:55 239
	current_state.current_puzzle = this->selected_puzzle;
4ebb3d36 Poul Sander 2025-10-05 11:55 240
	current_state.moves_allowed.resize(current_state.puzzle_count);
4ebb3d36 Poul Sander 2025-10-05 11:55 241
4ebb3d36 Poul Sander 2025-10-05 11:55 242
	for (int level = 0; level < current_state.puzzle_count; ++level) {
4ebb3d36 Poul Sander 2025-10-05 11:55 243
		current_state.moves_allowed[level] = PuzzleNumberOfMovesAllowed(level);
4ebb3d36 Poul Sander 2025-10-05 11:55 244
		for (int x = 0; x < 6; ++x) {
4ebb3d36 Poul Sander 2025-10-05 11:55 245
			for (int y = 0; y < 12; ++y) {
4ebb3d36 Poul Sander 2025-10-05 11:55 246
				current_state.puzzle_data[level][x][y] = PuzzleGetBrick(level, x, y);
4ebb3d36 Poul Sander 2025-10-05 11:55 247
			}
4ebb3d36 Poul Sander 2025-10-05 11:55 248
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 249
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 250
	undo_stack.push_back(current_state);
4ebb3d36 Poul Sander 2025-10-05 11:55 251
4ebb3d36 Poul Sander 2025-10-05 11:55 252
	PuzzleState next_state = redo_stack.back();
4ebb3d36 Poul Sander 2025-10-05 11:55 253
	redo_stack.pop_back();
4ebb3d36 Poul Sander 2025-10-05 11:55 254
4ebb3d36 Poul Sander 2025-10-05 11:55 255
	EditorResizePuzzleNumber(next_state.puzzle_count);
4ebb3d36 Poul Sander 2025-10-05 11:55 256
	for (int level = 0; level < next_state.puzzle_count; ++level) {
4ebb3d36 Poul Sander 2025-10-05 11:55 257
		PuzzleNumberOfMovesAllowedSet(level, next_state.moves_allowed[level]);
4ebb3d36 Poul Sander 2025-10-05 11:55 258
		for (int x = 0; x < 6; ++x) {
4ebb3d36 Poul Sander 2025-10-05 11:55 259
			for (int y = 0; y < 12; ++y) {
4ebb3d36 Poul Sander 2025-10-05 11:55 260
				PuzzleSetBrick(level, x, y, next_state.puzzle_data[level][x][y]);
4ebb3d36 Poul Sander 2025-10-05 11:55 261
			}
4ebb3d36 Poul Sander 2025-10-05 11:55 262
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 263
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 264
4ebb3d36 Poul Sander 2025-10-05 11:55 265
	this->selected_puzzle = next_state.current_puzzle;
4ebb3d36 Poul Sander 2025-10-05 11:55 266
	SavePuzzleStages();
4ebb3d36 Poul Sander 2025-10-05 11:55 267
}
4ebb3d36 Poul Sander 2025-10-05 11:55 268
4ebb3d36 Poul Sander 2025-10-05 11:55 269
bool PuzzleEditorState::CanUndo() const {
9d84cac6 Poul Sander 2025-10-07 18:43 270
	return undo_stack.size();
4ebb3d36 Poul Sander 2025-10-05 11:55 271
}
4ebb3d36 Poul Sander 2025-10-05 11:55 272
4ebb3d36 Poul Sander 2025-10-05 11:55 273
bool PuzzleEditorState::CanRedo() const {
9d84cac6 Poul Sander 2025-10-07 18:43 274
	return redo_stack.size();
4ebb3d36 Poul Sander 2025-10-05 11:55 275
}
4ebb3d36 Poul Sander 2025-10-05 11:55 276
b8a4e6f1 Poul Sander 2025-06-21 10:31 277
void PuzzleEditorState::BrickClicked(int x, int y) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 278
	if (read_only) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 279
		return;
b8a4e6f1 Poul Sander 2025-06-21 10:31 280
	}
b8a4e6f1 Poul Sander 2025-06-21 10:31 281
	if (x < 0 || x >= 6) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 282
		return;
b8a4e6f1 Poul Sander 2025-06-21 10:31 283
	}
b8a4e6f1 Poul Sander 2025-06-21 10:31 284
	if (y <0 || y >= 12) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 285
		return;
b8a4e6f1 Poul Sander 2025-06-21 10:31 286
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 287
4ebb3d36 Poul Sander 2025-10-05 11:55 288
	SaveCurrentState();
4ebb3d36 Poul Sander 2025-10-05 11:55 289
b8a4e6f1 Poul Sander 2025-06-21 10:31 290
	if (selected_action >= 0 && selected_action < 7) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 291
		PuzzleSetBrick(this->selected_puzzle, x, y, this->selected_action);
b8a4e6f1 Poul Sander 2025-06-21 10:31 292
	}
b8a4e6f1 Poul Sander 2025-06-21 10:31 293
	if (selected_action == selection_clear) {
b8a4e6f1 Poul Sander 2025-06-21 10:31 294
		PuzzleSetBrick(this->selected_puzzle, x, y, -1);
72e87270 Poul Sander 2025-06-21 15:22 295
	}
72e87270 Poul Sander 2025-06-21 15:22 296
	if (selected_action == selection_move_up) {
72e87270 Poul Sander 2025-06-21 15:22 297
		BricksMoveUp(this->selected_puzzle, x, y);
72e87270 Poul Sander 2025-06-21 15:22 298
	}
72e87270 Poul Sander 2025-06-21 15:22 299
	if (selected_action == selection_move_down) {
72e87270 Poul Sander 2025-06-21 15:22 300
		BricksMoveDown(this->selected_puzzle, x, y);
72e87270 Poul Sander 2025-06-21 15:22 301
	}
72e87270 Poul Sander 2025-06-21 15:22 302
	if (selected_action == selection_move_left) {
72e87270 Poul Sander 2025-06-21 15:22 303
		BricksMoveColumnLeft(this->selected_puzzle, x);
72e87270 Poul Sander 2025-06-21 15:22 304
	}
72e87270 Poul Sander 2025-06-21 15:22 305
	if (selected_action == selection_move_right) {
72e87270 Poul Sander 2025-06-21 15:22 306
		BricksMoveColumnRight(this->selected_puzzle, x);
b8a4e6f1 Poul Sander 2025-06-21 10:31 307
	}
f390a0aa Poul Sander 2025-10-05 12:24 308
	SavePuzzleStages();
b8a4e6f1 Poul Sander 2025-06-21 10:31 309
b8a4e6f1 Poul Sander 2025-06-21 10:31 310
}
b8a4e6f1 Poul Sander 2025-06-21 10:31 311
1873b078 Poul Sander 2025-02-06 22:01 312
void PuzzleEditorState::Draw(SDL_Renderer* target) {
6046ca3f Poul Sander 2025-04-06 16:14 313
	DrawBackground(target);
1fcc8881 Poul Sander 2025-05-15 18:54 314
1fcc8881 Poul Sander 2025-05-15 18:54 315
	ImGui::Begin("Board area");
1fcc8881 Poul Sander 2025-05-15 18:54 316
	ImGui::BeginChild("Test");
1fcc8881 Poul Sander 2025-05-15 18:54 317
	ImVec2 p = ImGui::GetCursorScreenPos();
636cde3b Poul Sander 2025-05-15 21:40 318
	ImVec2 size = ImGui::GetContentRegionAvail();
ee1c1ede Poul Sander 2025-10-07 19:28 319
	const int x_offset = p.x;
ee1c1ede Poul Sander 2025-10-07 19:28 320
	const int y_offset = p.y;
ee1c1ede Poul Sander 2025-10-07 19:28 321
	constexpr int height = BOARD_HEIGHT;
ee1c1ede Poul Sander 2025-10-07 19:28 322
	constexpr int width = BOARD_WIDTH;
636cde3b Poul Sander 2025-05-15 21:40 323
	window_resize.SetPhysicalSize(size.x, size.y);
636cde3b Poul Sander 2025-05-15 21:40 324
636cde3b Poul Sander 2025-05-15 21:40 325
59365d69 Poul Sander 2025-05-25 12:06 326
	int brick_size = 50;
59365d69 Poul Sander 2025-05-25 12:06 327
	window_resize.LogicalToPhysical(&brick_size, nullptr);
e1a54754 Poul Sander 2025-05-25 13:31 328
	brick_size -= window_resize.GetLeftMargin();
59365d69 Poul Sander 2025-05-25 12:06 329
	for (int i=0; i < 6; ++i) {
59365d69 Poul Sander 2025-05-25 12:06 330
		for (int j=0; j < 12; ++j) {
59365d69 Poul Sander 2025-05-25 12:06 331
			ImVec2 p1(i*50.0f, (11-j)*50.0f);
59365d69 Poul Sander 2025-05-25 12:06 332
			LogicalToPhysical(window_resize, p1);
ee1c1ede Poul Sander 2025-10-07 19:28 333
			p1.x += x_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 334
			p1.y += y_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 335
			const int brick = PuzzleGetBrick(this->selected_puzzle, i, j);
59365d69 Poul Sander 2025-05-25 12:06 336
			DrawBrick(brick, static_cast<int>(p1.x), static_cast<int>(p1.y), brick_size, brick_size);
59365d69 Poul Sander 2025-05-25 12:06 337
		}
59365d69 Poul Sander 2025-05-25 12:06 338
	}
59365d69 Poul Sander 2025-05-25 12:06 339
1fcc8881 Poul Sander 2025-05-15 18:54 340
	for (int i=0; i <= 6;++i) {
636cde3b Poul Sander 2025-05-15 21:40 341
		ImVec2 p1(i*50.0f, 0);
636cde3b Poul Sander 2025-05-15 21:40 342
		ImVec2 p2(i*50.0f, height);
636cde3b Poul Sander 2025-05-15 21:40 343
		LogicalToPhysical(window_resize, p1);
636cde3b Poul Sander 2025-05-15 21:40 344
		LogicalToPhysical(window_resize, p2);
ee1c1ede Poul Sander 2025-10-07 19:28 345
		p1.x += x_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 346
		p1.y += y_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 347
		p2.x += x_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 348
		p2.y += y_offset;
636cde3b Poul Sander 2025-05-15 21:40 349
		ImGui::GetWindowDrawList()->AddLine(p1, p2, IM_COL32(255, 0, 0, 100));
1fcc8881 Poul Sander 2025-05-15 18:54 350
	}
1fcc8881 Poul Sander 2025-05-15 18:54 351
	for (int i=0; i <= 12;++i) {
636cde3b Poul Sander 2025-05-15 21:40 352
		ImVec2 p1(0,i*50.0f);
636cde3b Poul Sander 2025-05-15 21:40 353
		ImVec2 p2(width, i*50.0f);
636cde3b Poul Sander 2025-05-15 21:40 354
		LogicalToPhysical(window_resize, p1);
636cde3b Poul Sander 2025-05-15 21:40 355
		LogicalToPhysical(window_resize, p2);
ee1c1ede Poul Sander 2025-10-07 19:28 356
		p1.x += x_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 357
		p1.y += y_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 358
		p2.x += x_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 359
		p2.y += y_offset;
636cde3b Poul Sander 2025-05-15 21:40 360
		ImGui::GetWindowDrawList()->AddLine(p1, p2, IM_COL32(255, 0, 0, 100));
6046ca3f Poul Sander 2025-04-06 16:14 361
	}
ee1c1ede Poul Sander 2025-10-07 19:28 362
	const ImGuiIO& io = ImGui::GetIO();
37278577 Poul Sander 2025-06-21 07:50 363
	if (ImGui::IsMouseReleased(0) && io.MouseDownDurationPrev[0] < 0.3f && !ImGui::IsMouseDragPastThreshold(0)) {
37278577 Poul Sander 2025-06-21 07:50 364
		ImVec2 pos = io.MousePos;
ee1c1ede Poul Sander 2025-10-07 19:28 365
		pos.x -= x_offset;
ee1c1ede Poul Sander 2025-10-07 19:28 366
		pos.y -= y_offset;
37278577 Poul Sander 2025-06-21 07:50 367
		int logical_pos_x = 0;
37278577 Poul Sander 2025-06-21 07:50 368
		int logical_pos_y = 0;
37278577 Poul Sander 2025-06-21 07:50 369
		window_resize.PhysicalToLogical(pos.x, pos.y, logical_pos_x, logical_pos_y);
37278577 Poul Sander 2025-06-21 07:50 370
		//std::cout << "Clicked at: " << pos.x << "," << pos.y << "\n";
37278577 Poul Sander 2025-06-21 07:50 371
		//std::cout << "Logical Pos: " << logical_pos_x << "," << logical_pos_y << "\n";
ee1c1ede Poul Sander 2025-10-07 19:28 372
		const int board_x = logical_pos_x / 50;
ee1c1ede Poul Sander 2025-10-07 19:28 373
		const int board_y = 11-(logical_pos_y / 50);
37278577 Poul Sander 2025-06-21 07:50 374
		if (board_x >=0 && board_x < 6 && board_y >= 0 && board_y < 12) {
37278577 Poul Sander 2025-06-21 07:50 375
			std::cout << "Board Pos: " << board_x << "," << board_y << "\n";
b8a4e6f1 Poul Sander 2025-06-21 10:31 376
			BrickClicked(board_x, board_y);
37278577 Poul Sander 2025-06-21 07:50 377
		}
37278577 Poul Sander 2025-06-21 07:50 378
37278577 Poul Sander 2025-06-21 07:50 379
	}
1fcc8881 Poul Sander 2025-05-15 18:54 380
	ImGui::EndChild();
1fcc8881 Poul Sander 2025-05-15 18:54 381
	ImGui::End();
1fcc8881 Poul Sander 2025-05-15 18:54 382
1873b078 Poul Sander 2025-02-06 22:01 383
	ImGui::Begin("File list", nullptr, ImGuiWindowFlags_NoCollapse);
a80f6a78 Poul Sander 2025-04-04 18:34 384
	for (const auto& file : this->puzzle_files) {
a80f6a78 Poul Sander 2025-04-04 18:34 385
		if (ImGui::Selectable(file.c_str(), this->selected_file == file)) {
a80f6a78 Poul Sander 2025-04-04 18:34 386
			SelectFile(file);
a80f6a78 Poul Sander 2025-04-04 18:34 387
		}
1873b078 Poul Sander 2025-02-06 22:01 388
	}
1873b078 Poul Sander 2025-02-06 22:01 389
e48b9d40 Poul Sander 2025-10-07 20:08 390
	ImGui::Separator();
e48b9d40 Poul Sander 2025-10-07 20:08 391
	ImGui::InputText("##newfilename", new_filename_buffer, sizeof(new_filename_buffer));
e48b9d40 Poul Sander 2025-10-07 20:08 392
	if (ImGui::Button("Create file")) {
e48b9d40 Poul Sander 2025-10-07 20:08 393
		std::string new_file(new_filename_buffer);
e48b9d40 Poul Sander 2025-10-07 20:08 394
		if (new_file.size()) {
e48b9d40 Poul Sander 2025-10-07 20:08 395
			const auto it = std::find(puzzle_files.begin(), puzzle_files.end(), new_file);
e48b9d40 Poul Sander 2025-10-07 20:08 396
			if (it == puzzle_files.end()) {
e48b9d40 Poul Sander 2025-10-07 20:08 397
				puzzle_files.push_back(new_file);
e48b9d40 Poul Sander 2025-10-07 20:08 398
				std::sort(puzzle_files.begin(), puzzle_files.end());
e48b9d40 Poul Sander 2025-10-07 20:08 399
				sago::WriteFileContent(fmt::format("puzzles/{}", new_file).c_str(), "0"); // Create file with 0 puzzles in it
e48b9d40 Poul Sander 2025-10-07 20:08 400
				SelectFile(new_file);
e48b9d40 Poul Sander 2025-10-07 20:08 401
			}
e48b9d40 Poul Sander 2025-10-07 20:08 402
		}
e48b9d40 Poul Sander 2025-10-07 20:08 403
	}
e48b9d40 Poul Sander 2025-10-07 20:08 404
a80f6a78 Poul Sander 2025-04-04 18:34 405
	ImGui::End();
a80f6a78 Poul Sander 2025-04-04 18:34 406
	ImGui::Begin("Puzzles in file");
ee1c1ede Poul Sander 2025-10-07 19:28 407
	const int puzzle_count = PuzzleGetNumberOfPuzzles();
a80f6a78 Poul Sander 2025-04-04 18:34 408
	for (int i = 0; i < puzzle_count; ++i) {
6046ca3f Poul Sander 2025-04-06 16:14 409
		if (ImGui::Selectable(std::to_string(i).c_str(), this->selected_puzzle == i)) {
6046ca3f Poul Sander 2025-04-06 16:14 410
			this->selected_puzzle = i;
a80f6a78 Poul Sander 2025-04-04 18:34 411
		}
a80f6a78 Poul Sander 2025-04-04 18:34 412
	}
0305b768 Poul Sander 2025-07-17 14:08 413
	if (ImGui::Button("Add puzzle")) {
4ebb3d36 Poul Sander 2025-10-05 11:55 414
		if (!read_only) {
4ebb3d36 Poul Sander 2025-10-05 11:55 415
			SaveCurrentState();
4ebb3d36 Poul Sander 2025-10-05 11:55 416
			EditorAddPuzzle(this->selected_puzzle);
4ebb3d36 Poul Sander 2025-10-05 11:55 417
			SavePuzzleStages();
4ebb3d36 Poul Sander 2025-10-05 11:55 418
		}
0305b768 Poul Sander 2025-07-17 14:08 419
	}
0305b768 Poul Sander 2025-07-17 14:08 420
	if (ImGui::Button("Remove puzzle")) {
4ebb3d36 Poul Sander 2025-10-05 11:55 421
		if (!read_only) {
4ebb3d36 Poul Sander 2025-10-05 11:55 422
			SaveCurrentState();
4ebb3d36 Poul Sander 2025-10-05 11:55 423
			EditorRemovePuzzle(this->selected_puzzle);
4ebb3d36 Poul Sander 2025-10-05 11:55 424
			SavePuzzleStages();
4ebb3d36 Poul Sander 2025-10-05 11:55 425
		}
0305b768 Poul Sander 2025-07-17 14:08 426
	}
1873b078 Poul Sander 2025-02-06 22:01 427
	ImGui::End();
298835a8 Poul Sander 2025-05-31 20:49 428
298835a8 Poul Sander 2025-05-31 20:49 429
	ImGui::Begin("Palette");
52352a94 Poul Sander 2025-06-03 19:04 430
	for (size_t i = 0; i < 7; ++i) {
4ebb3d36 Poul Sander 2025-10-05 11:55 431
		if (ImGui::Selectable(fmt::format("##{}", i).c_str(), this->selected_action == static_cast<int>(i), 0, ImVec2(0,50))) {
4ebb3d36 Poul Sander 2025-10-05 11:55 432
			this->selected_action = static_cast<int>(i);
52352a94 Poul Sander 2025-06-03 19:04 433
		}
52352a94 Poul Sander 2025-06-03 19:04 434
		ImGui::SameLine();
52352a94 Poul Sander 2025-06-03 19:04 435
		sago::SagoSprite& sprite = globalData.bricks[i];
52352a94 Poul Sander 2025-06-03 19:04 436
		ImGuiWritePartOfTexture(sprite.GetTextureHandler().get(), sprite.GetImageCord().x, sprite.GetImageCord().y, sprite.GetWidth(), sprite.GetHeight(), 50, 50);
298835a8 Poul Sander 2025-05-31 20:49 437
	}
298835a8 Poul Sander 2025-05-31 20:49 438
	if (ImGui::Selectable("Clear", this->selected_action == selection_clear)) {
298835a8 Poul Sander 2025-05-31 20:49 439
		this->selected_action = selection_clear;
298835a8 Poul Sander 2025-05-31 20:49 440
	}
298835a8 Poul Sander 2025-05-31 20:49 441
	if (ImGui::Selectable("Move Up", this->selected_action == selection_move_up)) {
298835a8 Poul Sander 2025-05-31 20:49 442
		this->selected_action = selection_move_up;
298835a8 Poul Sander 2025-05-31 20:49 443
	}
0305b768 Poul Sander 2025-07-17 14:08 444
	/*if (ImGui::Selectable("Move down", this->selected_action == selection_move_down)) {
298835a8 Poul Sander 2025-05-31 20:49 445
		this->selected_action = selection_move_down;
298835a8 Poul Sander 2025-05-31 20:49 446
	}
298835a8 Poul Sander 2025-05-31 20:49 447
	if (ImGui::Selectable("Move left", this->selected_action == selection_move_left)) {
298835a8 Poul Sander 2025-05-31 20:49 448
		this->selected_action = selection_move_left;
298835a8 Poul Sander 2025-05-31 20:49 449
	}
298835a8 Poul Sander 2025-05-31 20:49 450
	if (ImGui::Selectable("Move right", this->selected_action == selection_move_right)) {
298835a8 Poul Sander 2025-05-31 20:49 451
		this->selected_action = selection_move_right;
0305b768 Poul Sander 2025-07-17 14:08 452
	}*/
298835a8 Poul Sander 2025-05-31 20:49 453
	ImGui::Separator();
298835a8 Poul Sander 2025-05-31 20:49 454
	ImGui::LabelText("moves allowed", "%i", PuzzleNumberOfMovesAllowed(this->selected_puzzle));
520e8c44 Poul Sander 2025-06-29 18:16 455
	if (ImGui::Button("+1 move")) {
4ebb3d36 Poul Sander 2025-10-05 11:55 456
		if (!read_only) {
4ebb3d36 Poul Sander 2025-10-05 11:55 457
			SaveCurrentState();
f390a0aa Poul Sander 2025-10-05 12:24 458
			PuzzleNumberOfMovesAllowedSet(this->selected_puzzle, PuzzleNumberOfMovesAllowed(this->selected_puzzle)+1);
f390a0aa Poul Sander 2025-10-05 12:24 459
			SavePuzzleStages();
4ebb3d36 Poul Sander 2025-10-05 11:55 460
		}
520e8c44 Poul Sander 2025-06-29 18:16 461
	}
520e8c44 Poul Sander 2025-06-29 18:16 462
	if (ImGui::Button("-1 move")) {
4ebb3d36 Poul Sander 2025-10-05 11:55 463
		if (!read_only) {
4ebb3d36 Poul Sander 2025-10-05 11:55 464
			SaveCurrentState();
f390a0aa Poul Sander 2025-10-05 12:24 465
			PuzzleNumberOfMovesAllowedSet(this->selected_puzzle, PuzzleNumberOfMovesAllowed(this->selected_puzzle)-1);
f390a0aa Poul Sander 2025-10-05 12:24 466
			SavePuzzleStages();
4ebb3d36 Poul Sander 2025-10-05 11:55 467
		}
520e8c44 Poul Sander 2025-06-29 18:16 468
	}
298835a8 Poul Sander 2025-05-31 20:49 469
	ImGui::Separator();
298835a8 Poul Sander 2025-05-31 20:49 470
	if (read_only) {
298835a8 Poul Sander 2025-05-31 20:49 471
		ImGui::LabelText("Read Only", "");
4ebb3d36 Poul Sander 2025-10-05 11:55 472
	} else {
ee1c1ede Poul Sander 2025-10-07 19:28 473
		const bool undo_available = CanUndo();
ee1c1ede Poul Sander 2025-10-07 19:28 474
		if (!undo_available) {
4ebb3d36 Poul Sander 2025-10-05 11:55 475
			ImGui::BeginDisabled();
4ebb3d36 Poul Sander 2025-10-05 11:55 476
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 477
		if (ImGui::Button("Undo (Ctrl+Z)")) {
4ebb3d36 Poul Sander 2025-10-05 11:55 478
			Undo();
4ebb3d36 Poul Sander 2025-10-05 11:55 479
		}
ee1c1ede Poul Sander 2025-10-07 19:28 480
		if (!undo_available) {
4ebb3d36 Poul Sander 2025-10-05 11:55 481
			ImGui::EndDisabled();
4ebb3d36 Poul Sander 2025-10-05 11:55 482
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 483
4ebb3d36 Poul Sander 2025-10-05 11:55 484
		ImGui::SameLine();
ee1c1ede Poul Sander 2025-10-07 19:28 485
		const bool redo_available = CanRedo();
4ebb3d36 Poul Sander 2025-10-05 11:55 486
ee1c1ede Poul Sander 2025-10-07 19:28 487
		if (!redo_available) {
4ebb3d36 Poul Sander 2025-10-05 11:55 488
			ImGui::BeginDisabled();
4ebb3d36 Poul Sander 2025-10-05 11:55 489
		}
4ebb3d36 Poul Sander 2025-10-05 11:55 490
		if (ImGui::Button("Redo (Ctrl+Y)")) {
4ebb3d36 Poul Sander 2025-10-05 11:55 491
			Redo();
4ebb3d36 Poul Sander 2025-10-05 11:55 492
		}
ee1c1ede Poul Sander 2025-10-07 19:28 493
		if (!redo_available) {
4ebb3d36 Poul Sander 2025-10-05 11:55 494
			ImGui::EndDisabled();
4ebb3d36 Poul Sander 2025-10-05 11:55 495
		}
298835a8 Poul Sander 2025-05-31 20:49 496
	}
4ebb3d36 Poul Sander 2025-10-05 11:55 497
	ImGui::Separator();
af6d5a44 Poul Sander 2025-06-21 19:31 498
	if (ImGui::Button("Play")) {
af6d5a44 Poul Sander 2025-06-21 19:31 499
		SetSinglePuzzleMode(this->selected_puzzle);
af6d5a44 Poul Sander 2025-06-21 19:31 500
		runGame(Gametype::Puzzle, this->selected_puzzle);
af6d5a44 Poul Sander 2025-06-21 19:31 501
	}
298835a8 Poul Sander 2025-05-31 20:49 502
	ImGui::End();
1873b078 Poul Sander 2025-02-06 22:01 503
}
1873b078 Poul Sander 2025-02-06 22:01 504
1873b078 Poul Sander 2025-02-06 22:01 505
void PuzzleEditorState::Update() {
1873b078 Poul Sander 2025-02-06 22:01 506
}
1873b078 Poul Sander 2025-02-06 22:01 507
1970-01-01 00:00 508