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"
10#include "app/editor/editor.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;
61 ImVector<std::string> tile16_names;
62 for (int i = 0; i < 0x200; ++i) {
63 std::string str = core::UppercaseHexByte(all_tiles_types_[i]);
64 tile16_names.push_back(str);
65 }
66
67 *tile8_source_canvas_.mutable_labels(0) = tile16_names;
69 return absl::OkStatus();
70}
71
72absl::Status Tile16Editor::Update() {
74 return absl::InvalidArgumentError("Blockset not initialized, open a ROM.");
75 }
76
78 if (BeginTabBar("Tile16 Editor Tabs")) {
81 EndTabBar();
82 }
83
84 return absl::OkStatus();
85}
86
87absl::Status Tile16Editor::DrawMenu() {
88 if (BeginMenuBar()) {
89 if (BeginMenu("View")) {
90 Checkbox("Show Collision Types",
92 EndMenu();
93 }
94
95 EndMenuBar();
96 }
97
98 return absl::OkStatus();
99}
100
102 if (BeginTabItem("Tile16 Editing")) {
103 if (BeginTable("#Tile16EditorTable", 2, TABLE_BORDERS_RESIZABLE,
104 ImVec2(0, 0))) {
105 TableSetupColumn("Blockset", ImGuiTableColumnFlags_WidthFixed,
106 GetContentRegionAvail().x);
107 TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthStretch,
108 GetContentRegionAvail().x);
109 TableHeadersRow();
110 TableNextRow();
111 TableNextColumn();
113 if (!status_.ok()) {
114 EndTable();
115 }
116
117 TableNextColumn();
119 if (status_ != absl::OkStatus()) {
120 EndTable();
121 }
123
124 EndTable();
125 }
126
127 EndTabItem();
128 }
129}
130
159
160absl::Status Tile16Editor::DrawToCurrentTile16(ImVec2 click_position) {
161 constexpr int tile8_size = 8;
162 constexpr int tile16_size = 16;
163
164 // Calculate the tile index for x and y based on the click_position
165 // Adjusting for Tile16 (16x16) which contains 4 Tile8 (8x8)
166 int tile_index_x = static_cast<int>(click_position.x) / tile8_size;
167 int tile_index_y = static_cast<int>(click_position.y) / tile8_size;
168 std::cout << "Tile Index X: " << tile_index_x << std::endl;
169 std::cout << "Tile Index Y: " << tile_index_y << std::endl;
170
171 // Calculate the pixel start position within the Tile16
172 ImVec2 start_position;
173 start_position.x = tile_index_x * 0x40;
174 start_position.y = tile_index_y * 0x40;
175 std::cout << "Start Position X: " << start_position.x << std::endl;
176 std::cout << "Start Position Y: " << start_position.y << std::endl;
177
178 // Draw the Tile8 to the correct position within the Tile16
179 for (int y = 0; y < tile8_size; ++y) {
180 for (int x = 0; x < tile8_size; ++x) {
181 int pixel_index =
182 (start_position.y + y) * tile16_size + ((start_position.x) + x);
183 int gfx_pixel_index = y * tile8_size + x;
185 pixel_index,
186 current_gfx_individual_[current_tile8_].data()[gfx_pixel_index]);
187 }
188 }
189
190 return absl::OkStatus();
191}
192
194 auto ow_main_pal_group = rom()->palette_group().overworld_main;
195
196 if (BeginChild("Tile8 Selector", ImVec2(GetContentRegionAvail().x, 0x175),
197 true)) {
202 current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent(
203 ow_main_pal_group[0], current_palette_));
206 }
210 }
211 EndChild();
212
213 // The user selected a tile8
214 if (!tile8_source_canvas_.points().empty()) {
215 uint16_t x = tile8_source_canvas_.points().front().x / 16;
216 uint16_t y = tile8_source_canvas_.points().front().y / 16;
217
218 current_tile8_ = x + (y * 8);
220 current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent(
221 ow_main_pal_group[0], current_palette_));
224 }
225
226 if (BeginChild("Tile16 Editor Options",
227 ImVec2(GetContentRegionAvail().x, 0x50), true)) {
231 if (!tile8_source_canvas_.points().empty()) {
237 }
238 }
241 }
242 EndChild();
243 return absl::OkStatus();
244}
245
247 Separator();
248 Text("Tile16 ID: %d", current_tile16_);
249 Text("Tile8 ID: %d", current_tile8_);
250 Text("Options:");
253 if (notify_palette.modified()) {
254 auto palette = palettesets_[current_palette_].main;
255 auto value = notify_palette.get();
256 if (notify_palette.get() > 0x04 && notify_palette.get() < 0x06) {
257 palette = palettesets_[current_palette_].aux1;
258 value -= 0x04;
259 } else if (notify_palette.get() > 0x06) {
260 palette = palettesets_[current_palette_].aux2;
261 value -= 0x06;
262 }
263
264 if (value > 0x00) {
268
272 }
273 }
274
275 Checkbox("X Flip", &x_flip);
276 Checkbox("Y Flip", &y_flip);
277 Checkbox("Priority Tile", &priority_tile);
278
279 return absl::OkStatus();
280}
281
283 auto ow_main_pal_group = rom()->palette_group().overworld_main;
284
285 current_gfx_individual_.reserve(1024);
286
287 for (int index = 0; index < 1024; index++) {
288 std::vector<uint8_t> tile_data(0x40, 0x00);
289
290 // Copy the pixel data for the current tile into the vector
291 for (int ty = 0; ty < 8; ty++) {
292 for (int tx = 0; tx < 8; tx++) {
293 // Current Gfx Data is 16 sheets of 8x8 tiles ordered 16 wide by 4 tall
294
295 // Calculate the position in the tile data vector
296 int position = tx + (ty * 0x08);
297
298 // Calculate the position in the current gfx data
299 int num_columns = current_gfx_bmp_.width() / 8;
300 int x = (index % num_columns) * 8 + tx;
301 int y = (index / num_columns) * 8 + ty;
302 int gfx_position = x + (y * 0x100);
303
304 // Get the pixel value from the current gfx data
305 uint8_t value = current_gfx_bmp_.data()[gfx_position];
306
307 if (value & 0x80) {
308 value -= 0x88;
309 }
310
311 tile_data[position] = value;
312 }
313 }
314
315 current_gfx_individual_.emplace_back();
316 current_gfx_individual_[index].Create(0x08, 0x08, 0x08, tile_data);
317 RETURN_IF_ERROR(current_gfx_individual_[index].ApplyPaletteWithTransparent(
318 ow_main_pal_group[0], current_palette_));
320 }
321
323
324 return absl::OkStatus();
325}
326
327absl::Status Tile16Editor::SetCurrentTile(int id) {
328 current_tile16_ = id;
330 auto ow_main_pal_group = rom()->palette_group().overworld_main;
334 return absl::OkStatus();
335}
336
337#pragma mark - Tile16Transfer
338
340 if (BeginTabItem("Tile16 Transfer")) {
341 if (BeginTable("#Tile16TransferTable", 2, TABLE_BORDERS_RESIZABLE,
342 ImVec2(0, 0))) {
343 TableSetupColumn("Current ROM Tiles", ImGuiTableColumnFlags_WidthFixed,
344 GetContentRegionAvail().x / 2);
345 TableSetupColumn("Transfer ROM Tiles", ImGuiTableColumnFlags_WidthFixed,
346 GetContentRegionAvail().x / 2);
347 TableHeadersRow();
348 TableNextRow();
349
350 TableNextColumn();
352
353 TableNextColumn();
355
356 EndTable();
357 }
358
359 EndTabItem();
360 }
361 return absl::OkStatus();
362}
363
365 // Create a button for loading another ROM
366 if (Button("Load ROM")) {
367 ImGuiFileDialog::Instance()->OpenDialog(
368 "ChooseTransferFileDlgKey", "Open Transfer ROM", ".sfc,.smc", ".");
369 }
371 "ChooseTransferFileDlgKey", ".sfc,.smc", std::nullopt, [&]() {
372 std::string filePathName =
373 ImGuiFileDialog::Instance()->GetFilePathName();
375 transfer_started_ = true;
376 });
377
378 // TODO: Implement tile16 transfer
381
382 // Load the Link to the Past overworld.
386
387 // Create the tile16 blockset image
388 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
389 0x80, 0x2000, 0x80, transfer_overworld_.tile16_blockset_data(),
392 }
393
394 // Create a canvas for holding the tiles which will be exported
396 (8192 * 2), 0x20, transfer_blockset_loaded_, true,
397 3);
398
399 return absl::OkStatus();
400}
401
402} // namespace editor
403} // namespace app
404} // namespace yaze
static std::unordered_map< uint8_t, gfx::Paletteset > palettesets_
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:77
absl::Status LoadFromFile(const std::string &filename, bool z3_load=true)
Definition rom.cc:168
void UpdateBitmap(gfx::Bitmap *bitmap)
Used to update a bitmap on the screen.
Definition renderer.h:56
static Renderer & GetInstance()
Definition renderer.h:27
void RenderBitmap(gfx::Bitmap *bitmap)
Used to render a bitmap to the screen.
Definition renderer.h:49
core::NotifyValue< uint8_t > notify_palette
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
Represents a bitmap image.
Definition bitmap.h:67
absl::Status ApplyPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
Definition bitmap.cc:380
absl::Status ApplyPalette(const SnesPalette &palette)
Copy color data from the SnesPalette into the SDL_Palette.
Definition bitmap.cc:327
void WriteToPixel(int position, uchar value)
Definition bitmap.h:134
int width() const
Definition bitmap.h:172
auto data() const
Definition bitmap.h:176
bool DrawTileSelector(int size)
Definition canvas.cc:340
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), bool drag=false)
Definition canvas.cc:66
int GetTileIdFromMousePos()
Definition canvas.h:133
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
Definition canvas.cc:686
void DrawBitmap(const Bitmap &bitmap, int border_offset=0, bool ready=true)
Definition canvas.cc:461
auto mutable_labels(int i)
Definition canvas.h:175
auto drawn_tile_position() const
Definition canvas.h:159
auto points() const
Definition canvas.h:153
bool DrawTilePainter(const Bitmap &bitmap, int size, float scale=1.0f)
Definition canvas.cc:206
void DrawContextMenu(gfx::Bitmap *bitmap=nullptr)
Definition canvas.cc:101
auto custom_labels_enabled()
Definition canvas.h:163
#define TABLE_BORDERS_RESIZABLE
Definition constants.h:102
#define PRINT_IF_ERROR(expression)
Definition constants.h:36
#define RETURN_IF_ERROR(expression)
Definition constants.h:62
std::string UppercaseHexByte(uint8_t byte, bool leading)
Definition common.cc:103
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:175
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:266
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:832
Definition common.cc:22