6#include "absl/status/status.h"
7#include "absl/strings/str_cat.h"
8#include "absl/strings/str_format.h"
20#include "imgui/misc/cpp/imgui_stdlib.h"
32 std::string bankSTR = bank ?
"1st" :
"2nd";
34 bank ? absl::StrFormat(
"%X4", pos & 0xFFFF)
35 : absl::StrFormat(
"%X4", (pos -
kTextData2) & 0xFFFF);
36 std::string message = absl::StrFormat(
37 "There is too much text data in the %s block to save.\n"
38 "Available: %X4 | Used: %s",
39 bankSTR, space, posSTR);
44using ImGui::BeginChild;
45using ImGui::BeginTable;
49using ImGui::InputTextMultiline;
53using ImGui::Separator;
54using ImGui::TableHeadersRow;
55using ImGui::TableNextColumn;
56using ImGui::TableSetupColumn;
58using ImGui::TextWrapped;
61 ImGuiTableFlags_Borders |
62 ImGuiTableFlags_Resizable;
73 panel_manager->RegisterEditorPanel(
75 panel_manager->RegisterEditorPanel(
77 panel_manager->RegisterEditorPanel(std::make_unique<FontAtlasPanel>([
this]() {
81 panel_manager->RegisterEditorPanel(
82 std::make_unique<DictionaryPanel>([
this]() {
89 panel_manager->ShowPanel(session_id,
"message.message_list");
97 LOG_INFO(
"MessageEditor",
"Loaded %zu messages from ROM",
104 for (
int i = 0; i < 0x4000; i++) {
120 LOG_INFO(
"MessageEditor",
"Font bitmap created and texture queued");
124 if (load_font.ok()) {
137 LOG_ERROR(
"MessageEditor",
"No messages found in ROM!");
143 return absl::OkStatus();
150 return absl::OkStatus();
155 if (BeginChild(
"##MessagesList", ImVec2(0, 0),
true,
156 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
159 TableSetupColumn(
"ID");
160 TableSetupColumn(
"Contents");
161 TableSetupColumn(
"Data");
181 PushID(expanded_message.ID + 0x18D);
182 if (Button(
util::HexWord(expanded_message.ID + 0x18D).c_str())) {
193 TextWrapped(
"%s",
util::HexLong(expanded_message.Address).c_str());
205 ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
208 temp.erase(std::remove(temp.begin(), temp.end(),
'\n'), temp.end());
215 ImGui::BeginChild(
"##MessagePreview", ImVec2(0, 0),
true, 1);
216 Text(
"Message Preview");
217 if (Button(
"View Palette")) {
218 ImGui::OpenPopup(
"Palette");
220 if (ImGui::BeginPopup(
"Palette")) {
225 BeginChild(
"CurrentGfxFont", ImVec2(348, 0),
true,
226 ImGuiWindowFlags_NoScrollWithMouse);
232 if (ImGui::IsWindowHovered()) {
233 float wheel = ImGui::GetIO().MouseWheel;
236 }
else if (wheel < 0 &&
266 ImGui::BeginChild(
"##ExpandedMessageSettings", ImVec2(0, 100),
true,
267 ImGuiWindowFlags_AlwaysVerticalScrollbar);
268 ImGui::Text(
"Expanded Messages");
270 if (ImGui::Button(
"Load Expanded Message")) {
279 popup_manager->Show(
"Error");
288 if (ImGui::Button(
"Add New Message")) {
296 if (ImGui::Button(
"Save Expanded Messages")) {
306 if (ImGui::Button(
"Save As...")) {
315 if (ImGui::Button(
"Export to JSON")) {
327 ImGui::BeginChild(
"##TextCommands",
328 ImVec2(0, ImGui::GetContentRegionAvail().y / 2),
true,
329 ImGuiWindowFlags_AlwaysVerticalScrollbar);
330 static uint8_t command_parameter = 0;
332 for (
const auto& text_element : TextCommands) {
333 if (Button(text_element.GenericToken.c_str())) {
335 text_element.GetParamToken(command_parameter));
338 TextWrapped(
"%s", text_element.Description.c_str());
345 ImGui::BeginChild(
"##SpecialChars",
346 ImVec2(0, ImGui::GetContentRegionAvail().y / 2),
true,
347 ImGuiWindowFlags_AlwaysVerticalScrollbar);
348 for (
const auto& text_element : SpecialChars) {
349 if (Button(text_element.GenericToken.c_str())) {
353 TextWrapped(
"%s", text_element.Description.c_str());
360 if (ImGui::BeginChild(
"##DictionaryChild",
361 ImVec2(0, ImGui::GetContentRegionAvail().y),
true,
362 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
364 TableSetupColumn(
"ID");
365 TableSetupColumn(
"Contents");
371 Text(
"%s", dictionary.Contents.c_str());
385 LOG_WARN(
"MessageEditor",
"Preview data is empty, skipping bitmap update");
396 LOG_ERROR(
"MessageEditor",
"Bitmap surface is null after set_data()");
406 "Updated message preview bitmap (size: %zu) and queued texture update",
418 "Created message preview bitmap (%dx%d) with 8-bit depth and "
419 "queued texture creation",
425 std::vector<uint8_t> backup =
rom()->
vector();
433 bool in_second_bank =
false;
436 for (
const auto value : message.Data) {
443 return absl::InternalError(DisplayTextOverflowError(pos,
true));
448 in_second_bank =
true;
460 std::copy(backup.begin(), backup.end(),
rom()->mutable_data());
461 return absl::InternalError(DisplayTextOverflowError(pos,
false));
466 return absl::OkStatus();
471 return absl::InvalidArgumentError(
472 "No path specified for expanded messages");
501 if (expanded_message.Address + expanded_message.Data.size() >
504 expanded_message.Data.size() + 0x1000);
506 std::copy(expanded_message.Data.begin(), expanded_message.Data.end(),
522 return absl::OkStatus();
531 return absl::OkStatus();
536 if (ImGui::GetClipboardText() !=
nullptr) {
540 return absl::OkStatus();
549 return absl::OkStatus();
561 return absl::OkStatus();
567 return absl::OkStatus();
590 if (ImGui::Begin(
"Find Text",
nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
591 static char find_text[256] =
"";
592 ImGui::InputText(
"Search", find_text, IM_ARRAYSIZE(find_text));
594 if (ImGui::Button(
"Find Next")) {
599 if (ImGui::Button(
"Find All")) {
604 if (ImGui::Button(
"Replace")) {
614 return absl::OkStatus();
absl::Status LoadFromFile(const std::string &filename, const LoadOptions &options=LoadOptions::Defaults())
absl::Status WriteByte(int addr, uint8_t value)
const auto & vector() const
absl::Status SaveToFile(const SaveSettings &settings)
auto set_filename(std::string_view name)
zelda3::GameData * game_data() const
EditorDependencies dependencies_
std::vector< std::string > parsed_messages_
absl::Status Copy() override
std::vector< MessageData > expanded_messages_
absl::Status Find() override
absl::Status SaveExpandedMessages()
absl::Status Update() override
void DrawExpandedMessageSettings()
absl::Status Paste() override
gui::Canvas current_font_gfx16_canvas_
gui::Canvas font_gfx_canvas_
absl::Status Undo() override
absl::Status Load() override
std::array< uint8_t, 0x4000 > raw_font_gfx_data_
void Initialize() override
absl::Status Cut() override
void DrawMessagePreview()
Rom expanded_message_bin_
std::vector< MessageData > list_of_texts_
gfx::SnesPalette font_preview_colors_
MessageData current_message_
MessagePreview message_preview_
gui::TextBox message_text_box_
void DrawCurrentMessage()
void DrawSpecialCharacters()
absl::Status Redo() override
gfx::Bitmap current_font_gfx16_bitmap_
gfx::Bitmap font_gfx_bitmap_
std::string expanded_message_path_
absl::Status Save() override
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
void Create(int width, int height, int depth, std::span< uint8_t > data)
Create a bitmap with the given dimensions and data.
SnesPalette * mutable_palette()
void set_data(const std::vector< uint8_t > &data)
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap using SNES palette format.
SDL_Surface * surface() const
RAII timer for automatic timing management.
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale)
bool DrawTileSelector(int size, int size_y=0)
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0))
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
static std::string ShowSaveFileDialog(const std::string &default_name="", const std::string &default_extension="")
ShowSaveFileDialog opens a save file dialog and returns the selected filepath. Uses global feature fl...
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
#define LOG_DEBUG(category, format,...)
#define LOG_ERROR(category, format,...)
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
#define PRINT_IF_ERROR(expression)
std::string DisplayTextOverflowError(int pos, bool bank)
constexpr int kCharactersWidth
std::vector< MessageData > ReadAllTextData(uint8_t *rom, int pos)
absl::Status LoadExpandedMessages(std::string &expanded_message_path, std::vector< std::string > &parsed_messages, std::vector< MessageData > &expanded_messages, std::vector< DictionaryEntry > &dictionary)
constexpr int kCurrentMessageWidth
constexpr int kCurrentMessageHeight
constexpr uint8_t kBlockTerminator
constexpr int kFontGfxMessageSize
std::vector< std::string > ParseMessageData(std::vector< MessageData > &message_data, const std::vector< DictionaryEntry > &dictionary_entries)
constexpr uint8_t kMessageTerminator
constexpr int kFontGfxMessageDepth
constexpr int kTextData2End
std::vector< DictionaryEntry > BuildDictionaryEntries(Rom *rom)
std::vector< uint8_t > ParseMessageToData(std::string str)
absl::Status ExportMessagesToJson(const std::string &path, const std::vector< MessageData > &messages)
constexpr uint8_t kWidthArraySize
constexpr ImGuiTableFlags kMessageTableFlags
constexpr int kTextDataEnd
std::vector< uint8_t > SnesTo8bppSheet(std::span< uint8_t > sheet, int bpp, int num_sheets)
void EndCanvas(Canvas &canvas)
void BeginCanvas(Canvas &canvas, ImVec2 child_size)
void MemoryEditorPopup(const std::string &label, std::span< uint8_t > memory)
IMGUI_API bool DisplayPalette(gfx::SnesPalette &palette, bool loaded)
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
std::string HexWord(uint16_t word, HexStringParams params)
std::string HexLong(uint32_t dword, HexStringParams params)
absl::StatusOr< gfx::Bitmap > LoadFontGraphics(const Rom &rom)
Loads font graphics from ROM.
#define RETURN_IF_ERROR(expr)
PanelManager * panel_manager
PopupManager * popup_manager
std::vector< uint8_t > Data
std::vector< uint8_t > current_preview_data_
void DrawMessagePreview(const MessageData &message)
std::array< uint8_t, kWidthArraySize > width_array
std::vector< uint8_t > font_gfx16_data_2_
std::vector< uint8_t > font_gfx16_data_
std::vector< DictionaryEntry > all_dictionaries_
auto palette(int i) const
gfx::PaletteGroupMap palette_groups