yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
tile16_editor.cc
Go to the documentation of this file.
1#include "tile16_editor.h"
2
3#include <cmath>
4
5#include "ImGuiFileDialog/ImGuiFileDialog.h"
6#include "absl/status/status.h"
7#include "absl/status/statusor.h"
11#include "app/gfx/bitmap.h"
13#include "app/gfx/snes_tile.h"
14#include "app/gfx/tilesheet.h"
15#include "app/gui/canvas.h"
16#include "app/gui/icons.h"
17#include "app/gui/input.h"
18#include "app/gui/style.h"
19#include "app/rom.h"
21#include "imgui/imgui.h"
22
23namespace yaze {
24namespace app {
25namespace editor {
26
27using core::Renderer;
28
29using ImGui::BeginChild;
30using ImGui::BeginMenu;
31using ImGui::BeginMenuBar;
32using ImGui::BeginTabBar;
33using ImGui::BeginTabItem;
34using ImGui::BeginTable;
35using ImGui::Button;
36using ImGui::Checkbox;
37using ImGui::Combo;
38using ImGui::EndChild;
39using ImGui::EndMenu;
40using ImGui::EndMenuBar;
41using ImGui::EndTabBar;
42using ImGui::EndTabItem;
43using ImGui::EndTable;
44using ImGui::GetContentRegionAvail;
45using ImGui::Separator;
46using ImGui::TableHeadersRow;
47using ImGui::TableNextColumn;
48using ImGui::TableNextRow;
49using ImGui::TableSetupColumn;
50using ImGui::Text;
51
53 const gfx::Bitmap& tile16_blockset_bmp, const gfx::Bitmap& current_gfx_bmp,
54 const std::vector<gfx::Bitmap>& tile16_individual,
55 uint8_t all_tiles_types[0x200]) {
56 all_tiles_types_ = all_tiles_types;
57 tile16_blockset_bmp_ = tile16_blockset_bmp;
58 tile16_individual_ = tile16_individual;
59 current_gfx_bmp_ = current_gfx_bmp;
62 ImVector<std::string> tile16_names;
63 for (int i = 0; i < 0x200; ++i) {
64 std::string str = core::UppercaseHexByte(all_tiles_types_[i]);
65 tile16_names.push_back(str);
66 }
67
68 *tile8_source_canvas_.mutable_labels(0) = tile16_names;
70 return absl::OkStatus();
71}
72
73absl::Status Tile16Editor::Update() {
75 return absl::InvalidArgumentError("Blockset not initialized, open a ROM.");
76 }
77
79 if (BeginTabBar("Tile16 Editor Tabs")) {
82 EndTabBar();
83 }
84
85 return absl::OkStatus();
86}
87
88absl::Status Tile16Editor::DrawMenu() {
89 if (BeginMenuBar()) {
90 if (BeginMenu("View")) {
91 Checkbox("Show Collision Types",
93 EndMenu();
94 }
95
96 EndMenuBar();
97 }
98
99 return absl::OkStatus();
100}
101
103 if (BeginTabItem("Tile16 Editing")) {
104 if (BeginTable("#Tile16EditorTable", 2, TABLE_BORDERS_RESIZABLE,
105 ImVec2(0, 0))) {
106 TableSetupColumn("Blockset", ImGuiTableColumnFlags_WidthFixed,
107 GetContentRegionAvail().x);
108 TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthStretch,
109 GetContentRegionAvail().x);
110 TableHeadersRow();
111 TableNextRow();
112 TableNextColumn();
114 if (!status_.ok()) {
115 EndTable();
116 }
117
118 TableNextColumn();
120 if (status_ != absl::OkStatus()) {
121 EndTable();
122 }
124
125 EndTable();
126 }
127
128 EndTabItem();
129 }
130}
131
160
161absl::Status Tile16Editor::DrawToCurrentTile16(ImVec2 click_position) {
162 constexpr int tile8_size = 8;
163 constexpr int tile16_size = 16;
164
165 // Calculate the tile index for x and y based on the click_position
166 // Adjusting for Tile16 (16x16) which contains 4 Tile8 (8x8)
167 int tile_index_x = static_cast<int>(click_position.x) / tile8_size;
168 int tile_index_y = static_cast<int>(click_position.y) / tile8_size;
169 std::cout << "Tile Index X: " << tile_index_x << std::endl;
170 std::cout << "Tile Index Y: " << tile_index_y << std::endl;
171
172 // Calculate the pixel start position within the Tile16
173 ImVec2 start_position;
174 start_position.x = tile_index_x * 0x40;
175 start_position.y = tile_index_y * 0x40;
176 std::cout << "Start Position X: " << start_position.x << std::endl;
177 std::cout << "Start Position Y: " << start_position.y << std::endl;
178
179 // Draw the Tile8 to the correct position within the Tile16
180 for (int y = 0; y < tile8_size; ++y) {
181 for (int x = 0; x < tile8_size; ++x) {
182 int pixel_index =
183 (start_position.y + y) * tile16_size + ((start_position.x) + x);
184 int gfx_pixel_index = y * tile8_size + x;
186 pixel_index,
187 current_gfx_individual_[current_tile8_].data()[gfx_pixel_index]);
188 }
189 }
190
191 return absl::OkStatus();
192}
193
195 auto ow_main_pal_group = rom()->palette_group().overworld_main;
196
197 if (BeginChild("Tile8 Selector", ImVec2(GetContentRegionAvail().x, 0x175),
198 true)) {
203 current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent(
204 ow_main_pal_group[0], current_palette_));
207 }
211 }
212 EndChild();
213
214 // The user selected a tile8
215 if (!tile8_source_canvas_.points().empty()) {
216 uint16_t x = tile8_source_canvas_.points().front().x / 16;
217 uint16_t y = tile8_source_canvas_.points().front().y / 16;
218
219 current_tile8_ = x + (y * 8);
221 current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent(
222 ow_main_pal_group[0], current_palette_));
225 }
226
227 if (BeginChild("Tile16 Editor Options",
228 ImVec2(GetContentRegionAvail().x, 0x50), true)) {
232 if (!tile8_source_canvas_.points().empty()) {
238 }
239 }
242 }
243 EndChild();
244 return absl::OkStatus();
245}
246
248 Separator();
249 Text("Tile16 ID: %d", current_tile16_);
250 Text("Tile8 ID: %d", current_tile8_);
251 Text("Options:");
254 if (notify_palette.modified()) {
255 auto palette = palettesets_[current_palette_].main;
256 auto value = notify_palette.get();
257 if (notify_palette.get() > 0x04 && notify_palette.get() < 0x06) {
258 palette = palettesets_[current_palette_].aux1;
259 value -= 0x04;
260 } else if (notify_palette.get() > 0x06) {
261 palette = palettesets_[current_palette_].aux2;
262 value -= 0x06;
263 }
264
265 if (value > 0x00) {
269
273 }
274 }
275
276 Checkbox("X Flip", &x_flip);
277 Checkbox("Y Flip", &y_flip);
278 Checkbox("Priority Tile", &priority_tile);
279
280 return absl::OkStatus();
281}
282
284 auto ow_main_pal_group = rom()->palette_group().overworld_main;
285
286 current_gfx_individual_.reserve(1024);
287
288 for (int index = 0; index < 1024; index++) {
289 std::vector<uint8_t> tile_data(0x40, 0x00);
290
291 // Copy the pixel data for the current tile into the vector
292 for (int ty = 0; ty < 8; ty++) {
293 for (int tx = 0; tx < 8; tx++) {
294 // Current Gfx Data is 16 sheets of 8x8 tiles ordered 16 wide by 4 tall
295
296 // Calculate the position in the tile data vector
297 int position = tx + (ty * 0x08);
298
299 // Calculate the position in the current gfx data
300 int num_columns = current_gfx_bmp_.width() / 8;
301 int x = (index % num_columns) * 8 + tx;
302 int y = (index / num_columns) * 8 + ty;
303 int gfx_position = x + (y * 0x100);
304
305 // Get the pixel value from the current gfx data
306 uint8_t value = current_gfx_bmp_.data()[gfx_position];
307
308 if (value & 0x80) {
309 value -= 0x88;
310 }
311
312 tile_data[position] = value;
313 }
314 }
315
316 current_gfx_individual_.emplace_back();
317 current_gfx_individual_[index].Create(0x08, 0x08, 0x08, tile_data);
318 RETURN_IF_ERROR(current_gfx_individual_[index].ApplyPaletteWithTransparent(
319 ow_main_pal_group[0], current_palette_));
321 }
322
324
325 return absl::OkStatus();
326}
327
328absl::Status Tile16Editor::SetCurrentTile(int id) {
329 current_tile16_ = id;
331 auto ow_main_pal_group = rom()->palette_group().overworld_main;
335 return absl::OkStatus();
336}
337
338#pragma mark - Tile16Transfer
339
341 if (BeginTabItem("Tile16 Transfer")) {
342 if (BeginTable("#Tile16TransferTable", 2, TABLE_BORDERS_RESIZABLE,
343 ImVec2(0, 0))) {
344 TableSetupColumn("Current ROM Tiles", ImGuiTableColumnFlags_WidthFixed,
345 GetContentRegionAvail().x / 2);
346 TableSetupColumn("Transfer ROM Tiles", ImGuiTableColumnFlags_WidthFixed,
347 GetContentRegionAvail().x / 2);
348 TableHeadersRow();
349 TableNextRow();
350
351 TableNextColumn();
353
354 TableNextColumn();
356
357 EndTable();
358 }
359
360 EndTabItem();
361 }
362 return absl::OkStatus();
363}
364
366 // Create a button for loading another ROM
367 if (Button("Load ROM")) {
368 ImGuiFileDialog::Instance()->OpenDialog(
369 "ChooseTransferFileDlgKey", "Open Transfer ROM", ".sfc,.smc", ".");
370 }
372 "ChooseTransferFileDlgKey", ".sfc,.smc", std::nullopt, [&]() {
373 std::string filePathName =
374 ImGuiFileDialog::Instance()->GetFilePathName();
376 transfer_started_ = true;
377 });
378
379 // TODO: Implement tile16 transfer
382
383 // Load the Link to the Past overworld.
387
388 // Create the tile16 blockset image
389 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
390 0x80, 0x2000, 0x80, transfer_overworld_.tile16_blockset_data(),
393 }
394
395 // Create a canvas for holding the tiles which will be exported
397 (8192 * 2), 0x20, transfer_blockset_loaded_, true,
398 3);
399
400 return absl::OkStatus();
401}
402
403} // namespace editor
404} // namespace app
405} // namespace yaze
absl::Status LoadAllGraphicsData(bool defer_render=false)
This function iterates over all graphics sheets in the Rom and loads them into memory....
Definition rom.cc:83
absl::Status LoadFromFile(const std::string &filename, bool z3_load=true)
Definition rom.cc:142
static Renderer & GetInstance()
Definition renderer.h:30
void RenderBitmap(gfx::Bitmap *bitmap)
Used to render a bitmap to the screen.
Definition renderer.h:52
void UpdateBitmap(gfx::Bitmap *bitmap, bool use_sdl_update=false)
Used to update a bitmap on the screen.
Definition renderer.h:63
core::NotifyValue< uint8_t > notify_palette
std::vector< uint8_t > tile8_gfx_data_
std::vector< gfx::Bitmap > current_gfx_individual_
absl::Status DrawToCurrentTile16(ImVec2 pos)
absl::Status SetCurrentTile(int id)
absl::Status InitBlockset(const gfx::Bitmap &tile16_blockset_bmp, const gfx::Bitmap &current_gfx_bmp, const std::vector< gfx::Bitmap > &tile16_individual, uint8_t all_tiles_types[0x200])
std::vector< gfx::Bitmap > tile16_individual_
zelda3::overworld::Overworld transfer_overworld_
core::NotifyValue< uint32_t > notify_tile16
static std::unordered_map< uint8_t, gfx::Paletteset > palettesets_
Definition gfx_context.h:28
Represents a bitmap image.
Definition bitmap.h:70
auto vector() const
Definition bitmap.h:191
absl::Status ApplyPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
Definition bitmap.cc:399
absl::Status ApplyPalette(const SnesPalette &palette)
Copy color data from the SnesPalette into the SDL_Palette.
Definition bitmap.cc:346
void WriteToPixel(int position, uchar value)
Definition bitmap.h:141
int width() const
Definition bitmap.h:179
auto data() const
Definition bitmap.h:183
bool DrawTileSelector(int size)
Definition canvas.cc:343
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), bool drag=false)
Definition canvas.cc:69
int GetTileIdFromMousePos()
Definition canvas.h:123
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
Definition canvas.cc:689
void DrawBitmap(const Bitmap &bitmap, int border_offset=0, bool ready=true)
Definition canvas.cc:464
auto mutable_labels(int i)
Definition canvas.h:165
auto drawn_tile_position() const
Definition canvas.h:149
auto points() const
Definition canvas.h:143
bool DrawTilePainter(const Bitmap &bitmap, int size, float scale=1.0f)
Definition canvas.cc:209
void DrawContextMenu(gfx::Bitmap *bitmap=nullptr)
Definition canvas.cc:104
auto custom_labels_enabled()
Definition canvas.h:153
#define TABLE_BORDERS_RESIZABLE
Definition constants.h:109
#define PRINT_IF_ERROR(expression)
Definition constants.h:43
#define RETURN_IF_ERROR(expression)
Definition constants.h:69
std::string UppercaseHexByte(uint8_t byte, bool leading)
Definition labeling.cc:21
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:176
void EndPadding()
Definition style.cc:40
void FileDialogPipeline(absl::string_view display_key, absl::string_view file_extensions, std::optional< absl::string_view > button_text, std::function< void()> callback)
Definition input.cc:253
void BeginChildWithScrollbar(const char *str_id)
Definition style.cc:48
void BeginPadding(int i)
Definition style.cc:36
void BitmapCanvasPipeline(gui::Canvas &canvas, const gfx::Bitmap &bitmap, int width, int height, int tile_size, bool is_loaded, bool scrollbar, int canvas_id)
Definition canvas.cc:834
Definition common.cc:21