31 std::copy(binding->sheets.begin(), binding->sheets.end(),
current_sheets_);
43 if (sprite_id < 0 || sprite_id > 255)
44 return absl::OutOfRangeError(
"Sprite ID must be 0..255");
56 (layout ?
" (static pose copy)" :
" (empty template)");
57 copy.property_sprid.Text = std::to_string(sprite_id);
61 "vanilla." + std::to_string(sprite_id);
66 visible.push_back(
"sprite.custom_editor");
70 return absl::OkStatus();
76 return absl::FailedPreconditionError(
"Select a sprite asset");
77 if (slot < 0 || slot >= 8)
78 return absl::OutOfRangeError(
"Sprite graphics slot must be 0..7");
79 auto resolved_source = source;
80 if (resolved_source.kind ==
"bin" &&
project()) {
84 candidate.graphics_sources[slot] = resolved_source;
85 if (candidate.zsm_path.empty())
86 candidate.zsm_path =
"unsaved.zsm";
90 return validated.status();
91 const auto directory =
93 ? std::filesystem::path(
project()->filepath).parent_path()
94 : std::filesystem::path{};
98 if (!pixels.ok() && source.
kind !=
"sheet")
99 return pixels.status();
102 std::move(resolved_source);
106 return absl::OkStatus();
111 if (!binding || slot < 0 || slot >= 8 ||
112 binding->graphics_sources[slot].kind !=
"bin")
113 return absl::FailedPreconditionError(
"Select a bound BIN graphics slot");
116 return absl::FailedPreconditionError(
"Editor manager unavailable");
117 auto path = std::filesystem::path(binding->graphics_sources[slot].path);
118 if (path.is_relative()) {
120 return absl::FailedPreconditionError(
121 "Save the project to resolve this BIN path");
122 path = std::filesystem::path(
project()->filepath).parent_path() / path;
128 std::optional<zsprite::Frame> captured_frame;
129 std::string captured_label;
132 current_frame_ < static_cast<int>(sprite->editor.Frames.size())) {
134 captured_frame = frame;
135 captured_label = sprite->sprName +
" / frame " +
137 std::to_string(slot);
142 for (
const auto& tile : frame.Tiles)
144 palette = tile.palette;
149 return absl::FailedPreconditionError(
"Selected OAM palette unavailable");
151 auto* editors = manager->GetCurrentEditorSet();
152 if (!editors || !editors->GetGraphicsEditor())
153 return absl::FailedPreconditionError(
"Graphics editor unavailable");
154 const auto& source = binding->graphics_sources[slot];
156 path.lexically_normal().string(), source.bpp, source.offset,
158 if (captured_frame) {
159 editors->GetGraphicsEditor()->SetScratchPreview(
160 std::move(captured_label),
164 -> absl::StatusOr<usage_preview::PreviewImage> {
165 if (asset.
pixels.size() != 4096 || buffer.size() < 8 * 4096)
166 return absl::InvalidArgumentError(
167 "Sprite scratch slot has invalid dimensions");
168 auto updated = buffer;
170 updated.begin() + slot * 4096);
171 auto colors = palettes;
173 for (
const auto color : asset.
palette)
175 colors.palette_ref(palette) = std::move(row);
180 editors->GetGraphicsEditor()->SetScratchPreview({}, {});
183 return absl::OkStatus();
188 if (!binding || !ImGui::CollapsingHeader(
"Graphics sources"))
191 "Each slot holds 64 tiles (128 x 32 pixels). BIN and raw ROM ranges "
192 "are preview sources. Edit a BIN through Graphics > Scratch, export it, "
193 "then reload here. Raw ROM offsets are headerless PC byte offsets.");
199 : source.kind ==
"raw_rom" ? 2
209 constexpr const char* kinds[] = {
"ROM sheet",
"BIN file",
"Raw ROM range"};
213 ImGui::InputScalar(
"Byte offset (hex)", ImGuiDataType_U32,
215 ImGuiInputTextFlags_CharsHexadecimal);
220 if (ImGui::Button(
"Apply graphics source")) {
232 if (ImGui::Button(
"Reload graphics sources")) {
237 ImGui::Button(
"Edit bound BIN in Graphics Scratch"))
241 for (
int slot = 0; slot < 8; ++slot) {
242 const auto& source = binding->graphics_sources[slot];
243 if (source.kind !=
"sheet")
244 ImGui::TextWrapped(
"Slot %d: %s, %dbpp, offset $%08X %s", slot,
245 source.kind.c_str(), source.bpp, source.offset,
246 source.path.c_str());
251 const std::array<uint8_t, 8>& sheets,
252 const std::array<project::SpritePaletteBinding, 8>& rows) {
254 return absl::FailedPreconditionError(
"Select a sprite asset");
256 updated.sheets = sheets;
257 updated.palette_rows = rows;
258 auto validation = updated;
259 if (validation.zsm_path.empty())
260 validation.zsm_path =
"unsaved.zsm";
264 return parsed.status();
270 return absl::OkStatus();
275 const auto absolute =
276 std::filesystem::absolute(path).lexically_normal().string();
292 return absl::OkStatus();
300 return absl::FailedPreconditionError(
"Select a sprite asset");
301 const auto absolute =
302 std::filesystem::absolute(path).lexically_normal().string();
312 if (!loaded.ok() && result.ok())
324 if (!asset || asset->source_path.empty()) {
333 {
"draw", asset->source_path, asset->source_label, asset->draw_adapter});
337 asset->source_sha256)
339 "Draw source changed since import. Edited asset preserved; review "
348 return absl::FailedPreconditionError(
"Select a sprite asset");
363 if (!current || !ImGui::CollapsingHeader(
"Asset bindings"))
366 "Save the ZSM, then save the project to retain these bindings.");
367 if (!current->catalog_key.empty())
368 ImGui::TextWrapped(
"Catalog: %s", current->catalog_key.c_str());
369 if (!current->source_path.empty()) {
370 ImGui::TextWrapped(
"Source: %s : %s", current->source_path.c_str(),
371 current->source_label.c_str());
372 ImGui::TextWrapped(
"Adapter: %s", current->draw_adapter.c_str());
373 if (ImGui::Button(
"Check source hash"))
377 ?
"Source matched at last check"
380 constexpr const char* groups[] = {
"auto",
"global_sprites",
"sprites_aux1",
381 "sprites_aux2",
"sprites_aux3"};
382 auto rows = current->palette_rows;
383 bool changed =
false;
384 for (
int i = 0; i < 8; ++i) {
386 ImGui::Text(
"OAM palette %d", i);
388 for (
int j = 0; j < 5; ++j)
389 if (rows[i].group == groups[j])
391 if (ImGui::Combo(
"Group", &group, groups, 5)) {
392 rows[i].group = groups[group];
395 if (rows[i].group !=
"auto" &&
396 ImGui::InputInt(
"Palette index", &rows[i].index)) {
397 rows[i].index = std::clamp(rows[i].index, 0, 255);
The EditorManager controls the main editor window and manages the various editor classes.
zelda3::GameData * game_data() const
EditorDependencies dependencies_
absl::Status OpenSpriteAsset(const std::string &path)
int current_custom_sprite_index_
std::vector< project::SpriteAssetBinding > custom_sprite_bindings_
void DrawGraphicsSourceBindings()
absl::Status ReloadProjectSpriteAssets()
uint32_t graphics_source_offset_
int graphics_source_loaded_slot_
void DrawSpriteAssetBindings()
const zsprite::ZSprite * current_custom_sprite() const
absl::Status source_check_status_
void BeginUndoTransaction()
void RefreshSpritePreviewGraphics(bool use_asset_binding)
absl::StatusOr< std::string > ExportCurrentSpriteDraw()
int graphics_source_slot_
bool preview_needs_update_
int graphics_source_kind_
absl::Status OpenBoundBinInScratch(int slot)
absl::Status graphics_source_edit_status_
gfx::PaletteGroup sprite_palettes_
void LoadZsmFile(const std::string &path)
void ApplyCurrentSpriteBinding()
absl::Status CreateSpriteAssetFromVanilla(int sprite_id)
absl::Status palette_binding_status_
std::string behavior_candidate_
uint8_t vanilla_sheets_[8]
uint8_t current_sheets_[8]
absl::Status SaveSpriteAsset(const std::string &path)
std::vector< zsprite::ZSprite > custom_sprites_
std::vector< uint8_t > sprite_gfx_buffer_
char graphics_source_path_[4097]
project::YazeProject * project() const
int current_animation_index_
absl::Status SetSpriteGraphicsSource(int slot, const project::SpriteGraphicsSource &source)
const project::SpriteAssetBinding * current_sprite_binding() const
absl::Status behavior_status_
void SaveZsmFile(const std::string &path)
void CommitUndoTransaction()
absl::Status graphics_binding_status_
int graphics_source_document_
absl::Status CheckCurrentSpriteSource()
std::vector< std::string > custom_sprite_paths_
absl::Status SetSpriteGraphics(const std::array< uint8_t, 8 > &sheets, const std::array< project::SpritePaletteBinding, 8 > &rows)
void SetVisibleWindows(size_t session_id, const std::vector< std::string > &window_ids)
Set which panels should be visible for a session.
std::vector< std::string > GetVisibleWindowIds(size_t session_id) const
Get list of currently visible panel IDs for a session.
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
void AddColor(const SnesColor &color)
static const SpriteOamLayout * GetLayout(uint8_t sprite_id)
Get the OAM layout for a sprite ID.
static const SpriteOamLayout * GetPreviewOverride(uint8_t sprite_id, std::string_view hack_name)
std::string ComputeSourceArtifactSha256(std::string_view content)
absl::StatusOr< std::string > ExportDrawTables(const zsprite::ZSprite &sprite)
absl::Status ValidateDrawAdapter(const zsprite::ZSprite &sprite, const std::string &adapter)
zsprite::Frame CopyVanillaLayout(const zelda3::SpriteOamLayout &layout)
absl::StatusOr< usage_preview::PreviewImage > RenderFrameBuffer(const zsprite::Frame &frame, std::span< const uint8_t > buffer, const gfx::PaletteGroup &palettes)
absl::StatusOr< std::vector< uint8_t > > Resolve(const project::SpriteGraphicsSource &source, uint16_t sheet, const zelda3::GameData *data, const Rom *rom, const std::filesystem::path &project_directory)
Editors are the view controllers for the application.
nlohmann::json SpriteAssetToJson(const SpriteAssetBinding &asset)
absl::StatusOr< SpriteAssetBinding > SpriteAssetFromJson(const nlohmann::json &value)
absl::StatusOr< SpriteSourceDocument > ReadSpriteSource(const std::string &source_root, const SpriteSourceBinding &binding)
const std::string kSpriteDefaultNames[256]
constexpr int SpriteSlotForTile(int tile)
Slot (0-7) holding 8x8 OAM tile tile (name-table bit included).
#define RETURN_IF_ERROR(expr)
WorkspaceWindowManager * window_manager
std::vector< uint8_t > pixels
std::array< uint16_t, 16 > palette
const SnesPalette & palette_ref(int i) const
std::vector< SpriteAssetBinding > sprite_assets
std::string GetAbsolutePath(const std::string &relative_path) const