yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
sprite_editor.cc
Go to the documentation of this file.
1#include "sprite_editor.h"
2
5#include "util/file_util.h"
7#include "app/gfx/arena.h"
8#include "app/gui/icons.h"
9#include "app/gui/input.h"
11#include "util/hex.h"
12
13namespace yaze {
14namespace editor {
15
16using ImGui::BeginTable;
17using ImGui::Button;
18using ImGui::EndTable;
19using ImGui::Selectable;
20using ImGui::Separator;
21using ImGui::TableHeadersRow;
22using ImGui::TableNextColumn;
23using ImGui::TableNextRow;
24using ImGui::TableSetupColumn;
25using ImGui::Text;
26
28 // Register cards with EditorCardManager during initialization (once)
29 auto& card_manager = gui::EditorCardManager::Get();
30
31 card_manager.RegisterCard({
32 .card_id = "sprite.vanilla_editor",
33 .display_name = "Vanilla Sprites",
34 .icon = ICON_MD_SMART_TOY,
35 .category = "Sprite",
36 .shortcut_hint = "Alt+Shift+1",
37 .visibility_flag = &show_vanilla_editor_,
38 .priority = 10
39 });
40
41 card_manager.RegisterCard({
42 .card_id = "sprite.custom_editor",
43 .display_name = "Custom Sprites",
44 .icon = ICON_MD_ADD_CIRCLE,
45 .category = "Sprite",
46 .shortcut_hint = "Alt+Shift+2",
47 .visibility_flag = &show_custom_editor_,
48 .priority = 20
49 });
50}
51
52absl::Status SpriteEditor::Load() {
53 gfx::ScopedTimer timer("SpriteEditor::Load");
54 return absl::OkStatus();
55}
56
57absl::Status SpriteEditor::Update() {
58 if (rom()->is_loaded() && !sheets_loaded_) {
59 // Load the values for current_sheets_ array
60 sheets_loaded_ = true;
61 }
62
65
66 // Create session-aware cards (non-static for multi-session support)
67 gui::EditorCard vanilla_card(MakeCardTitle("Vanilla Sprites").c_str(), ICON_MD_PEST_CONTROL_RODENT);
68 gui::EditorCard custom_card(MakeCardTitle("Custom Sprites").c_str(), ICON_MD_ADD_MODERATOR);
69
71 if (vanilla_card.Begin(&show_vanilla_editor_)) {
73 }
74 vanilla_card.End(); // ALWAYS call End after Begin
75 }
76
78 if (custom_card.Begin(&show_custom_editor_)) {
80 }
81 custom_card.End(); // ALWAYS call End after Begin
82 }
83
84 return status_.ok() ? absl::OkStatus() : status_;
85}
86
88 static gui::Toolset toolbar;
89 toolbar.Begin();
90
91 if (toolbar.AddAction(ICON_MD_PEST_CONTROL_RODENT, "Vanilla Sprites")) {
93 }
94 if (toolbar.AddAction(ICON_MD_ADD_MODERATOR, "Custom Sprites")) {
96 }
97
98 toolbar.End();
99}
100
101
103 if (ImGui::BeginTable("##SpriteCanvasTable", 3, ImGuiTableFlags_Resizable,
104 ImVec2(0, 0))) {
105 TableSetupColumn("Sprites List", ImGuiTableColumnFlags_WidthFixed, 256);
106 TableSetupColumn("Canvas", ImGuiTableColumnFlags_WidthStretch,
107 ImGui::GetContentRegionAvail().x);
108 TableSetupColumn("Tile Selector", ImGuiTableColumnFlags_WidthFixed, 256);
109 TableHeadersRow();
110 TableNextRow();
111
112 TableNextColumn();
114
115 TableNextColumn();
116 static int next_tab_id = 0;
117
118 if (ImGui::BeginTabBar("SpriteTabBar", kSpriteTabBarFlags)) {
119 if (ImGui::TabItemButton(ICON_MD_ADD, kSpriteTabBarFlags)) {
120 if (std::find(active_sprites_.begin(), active_sprites_.end(),
122 // Room is already open
123 next_tab_id++;
124 }
125 active_sprites_.push_back(next_tab_id++); // Add new tab
126 }
127
128 // Submit our regular tabs
129 for (int n = 0; n < active_sprites_.Size;) {
130 bool open = true;
131
132 if (active_sprites_[n] > sizeof(zelda3::kSpriteDefaultNames) / 4) {
133 active_sprites_.erase(active_sprites_.Data + n);
134 continue;
135 }
136
137 if (ImGui::BeginTabItem(
138 zelda3::kSpriteDefaultNames[active_sprites_[n]].data(), &open,
139 ImGuiTabItemFlags_None)) {
141 ImGui::EndTabItem();
142 }
143
144 if (!open)
145 active_sprites_.erase(active_sprites_.Data + n);
146 else
147 n++;
148 }
149
150 ImGui::EndTabBar();
151 }
152
153 TableNextColumn();
154 if (sheets_loaded_) {
156 }
157 ImGui::EndTable();
158 }
159}
160
162 static bool flip_x = false;
163 static bool flip_y = false;
164 if (ImGui::BeginChild(gui::GetID("##SpriteCanvas"),
165 ImGui::GetContentRegionAvail(), true)) {
170
171 // Draw a table with OAM configuration
172 // X, Y, Tile, Palette, Priority, Flip X, Flip Y
173 if (ImGui::BeginTable("##OAMTable", 7, ImGuiTableFlags_Resizable,
174 ImVec2(0, 0))) {
175 TableSetupColumn("X", ImGuiTableColumnFlags_WidthStretch);
176 TableSetupColumn("Y", ImGuiTableColumnFlags_WidthStretch);
177 TableSetupColumn("Tile", ImGuiTableColumnFlags_WidthStretch);
178 TableSetupColumn("Palette", ImGuiTableColumnFlags_WidthStretch);
179 TableSetupColumn("Priority", ImGuiTableColumnFlags_WidthStretch);
180 TableSetupColumn("Flip X", ImGuiTableColumnFlags_WidthStretch);
181 TableSetupColumn("Flip Y", ImGuiTableColumnFlags_WidthStretch);
182 TableHeadersRow();
183 TableNextRow();
184
185 TableNextColumn();
187
188 TableNextColumn();
190
191 TableNextColumn();
193
194 TableNextColumn();
196
197 TableNextColumn();
199
200 TableNextColumn();
201 if (ImGui::Checkbox("##XFlip", &flip_x)) {
202 oam_config_.flip_x = flip_x;
203 }
204
205 TableNextColumn();
206 if (ImGui::Checkbox("##YFlip", &flip_y)) {
207 oam_config_.flip_y = flip_y;
208 }
209
210 ImGui::EndTable();
211 }
212
214
216
217 ImGui::EndChild();
218 }
219}
220
222 if (ImGui::BeginChild(gui::GetID("sheet_label"),
223 ImVec2(ImGui::GetContentRegionAvail().x, 0), true,
224 ImGuiWindowFlags_NoDecoration)) {
225 for (int i = 0; i < 8; i++) {
226 std::string sheet_label = absl::StrFormat("Sheet %d", i);
227 gui::InputHexByte(sheet_label.c_str(), &current_sheets_[i]);
228 if (i % 2 == 0) ImGui::SameLine();
229 }
230
234 for (int i = 0; i < 8; i++) {
236 gfx::Arena::Get().gfx_sheets().at(current_sheets_[i]), 1,
237 (i * 0x40) + 1, 2);
238 }
241 }
242 ImGui::EndChild();
243}
244
246 if (ImGui::BeginChild(gui::GetID("##SpritesList"),
247 ImVec2(ImGui::GetContentRegionAvail().x, 0), true,
248 ImGuiWindowFlags_NoDecoration)) {
249 int i = 0;
250 for (const auto each_sprite_name : zelda3::kSpriteDefaultNames) {
252 current_sprite_id_ == i, "Sprite Names", util::HexByte(i),
253 zelda3::kSpriteDefaultNames[i].data());
254 if (ImGui::IsItemClicked()) {
256 if (!active_sprites_.contains(i)) {
257 active_sprites_.push_back(i);
258 }
259 }
260 i++;
261 }
262 ImGui::EndChild();
263 }
264}
265
267 if (ImGui::Button("Add Frame")) {
268 // Add a new frame
269 }
270 if (ImGui::Button("Remove Frame")) {
271 // Remove the current frame
272 }
273}
274
276 if (BeginTable("##CustomSpritesTable", 3,
277 ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders |
278 ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable,
279 ImVec2(0, 0))) {
280 TableSetupColumn("Metadata", ImGuiTableColumnFlags_WidthFixed, 256);
281 TableSetupColumn("Canvas", ImGuiTableColumnFlags_WidthFixed, 256);
282 TableSetupColumn("TIlesheets", ImGuiTableColumnFlags_WidthFixed, 256);
283
284 TableHeadersRow();
285 TableNextRow();
286 TableNextColumn();
287
288 Separator();
290
291 TableNextColumn();
293
294 TableNextColumn();
296
297 EndTable();
298 }
299}
300
302 // ZSprite Maker format open file dialog
303 if (ImGui::Button("Open ZSprite")) {
304 // Open ZSprite file
305 std::string file_path = util::FileDialogWrapper::ShowOpenFileDialog();
306 if (!file_path.empty()) {
307 zsprite::ZSprite zsprite;
308 status_ = zsprite.Load(file_path);
309 if (status_.ok()) {
310 custom_sprites_.push_back(zsprite);
311 }
312 }
313 }
314
315 for (const auto custom_sprite : custom_sprites_) {
316 Selectable("%s", custom_sprite.sprName.c_str());
317 if (ImGui::IsItemClicked()) {
318 current_sprite_id_ = 256 + stoi(custom_sprite.property_sprid.Text);
319 if (!active_sprites_.contains(current_sprite_id_)) {
321 }
322 }
323 Separator();
324 }
325
326 for (const auto custom_sprite : custom_sprites_) {
327 // Draw the custom sprite metadata
328 Text("Sprite ID: %s", custom_sprite.property_sprid.Text.c_str());
329 Text("Sprite Name: %s", custom_sprite.property_sprname.Text.c_str());
330 Text("Sprite Palette: %s", custom_sprite.property_palette.Text.c_str());
331 Separator();
332 }
333}
334
335} // namespace editor
336} // namespace yaze
core::ResourceLabelManager * resource_label()
Definition rom.h:220
std::string MakeCardTitle(const std::string &base_title) const
Definition editor.h:127
ImVector< int > active_sprites_
void DrawAnimationFrames()
Draws the animation frames manager.
void DrawCurrentSheets()
Draws the current sheets.
void DrawSpriteCanvas()
Draws the sprite canvas.
absl::Status Update() override
void DrawSpritesList()
Draws the sprites list.
std::vector< zsprite::ZSprite > custom_sprites_
absl::Status Load() override
static Arena & Get()
Definition arena.cc:15
RAII timer for automatic timing management.
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale)
Definition canvas.cc:1062
void DrawContextMenu()
Definition canvas.cc:441
bool DrawTileSelector(int size, int size_y=0)
Definition canvas.cc:920
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0))
Definition canvas.cc:381
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
Definition canvas.cc:1386
static EditorCardManager & Get()
Draggable, dockable card for editor sub-windows.
bool Begin(bool *p_open=nullptr)
Ultra-compact toolbar that merges mode buttons with settings.
bool AddAction(const char *icon, const char *tooltip)
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
#define ICON_MD_ADD_MODERATOR
Definition icons.h:100
#define ICON_MD_ADD
Definition icons.h:84
#define ICON_MD_PEST_CONTROL_RODENT
Definition icons.h:1428
#define ICON_MD_ADD_CIRCLE
Definition icons.h:93
#define ICON_MD_SMART_TOY
Definition icons.h:1779
constexpr ImGuiTabBarFlags kSpriteTabBarFlags
void VerticalSpacing(float pixels)
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
Definition input.cc:175
ImGuiID GetID(const std::string &id)
Definition input.cc:339
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:189
std::string HexByte(uint8_t byte, HexStringParams params)
Definition hex.cc:30
Main namespace for the application.
void SelectableLabelWithNameEdit(bool selected, const std::string &type, const std::string &key, const std::string &defaultValue)
Definition project.cc:855
absl::Status Load(const std::string &filename)
Definition zsprite.h:74