6#include "absl/status/status.h"
7#include "absl/strings/str_cat.h"
8#include "absl/strings/str_format.h"
21#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(std::make_unique<MessageListPanel>(
75 panel_manager->RegisterEditorPanel(std::make_unique<MessageEditorPanel>(
77 panel_manager->RegisterEditorPanel(std::make_unique<FontAtlasPanel>([
this]() {
81 panel_manager->RegisterEditorPanel(std::make_unique<DictionaryPanel>([
this]() {
88 panel_manager->ShowPanel(session_id,
"message.message_list");
102 for (
int i = 0; i < 0x4000; i++) {
118 LOG_INFO(
"MessageEditor",
"Font bitmap created and texture queued");
122 if (load_font.ok()) {
135 LOG_ERROR(
"MessageEditor",
"No messages found in ROM!");
141 return absl::OkStatus();
148 return absl::OkStatus();
153 if (BeginChild(
"##MessagesList", ImVec2(0, 0),
true,
154 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
157 TableSetupColumn(
"ID");
158 TableSetupColumn(
"Contents");
159 TableSetupColumn(
"Data");
179 PushID(expanded_message.ID + 0x18D);
180 if (Button(
util::HexWord(expanded_message.ID + 0x18D).c_str())) {
191 TextWrapped(
"%s",
util::HexLong(expanded_message.Address).c_str());
203 ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
206 temp.erase(std::remove(temp.begin(), temp.end(),
'\n'), temp.end());
213 ImGui::BeginChild(
"##MessagePreview", ImVec2(0, 0),
true, 1);
214 Text(
"Message Preview");
215 if (Button(
"View Palette")) {
216 ImGui::OpenPopup(
"Palette");
218 if (ImGui::BeginPopup(
"Palette")) {
223 BeginChild(
"CurrentGfxFont", ImVec2(348, 0),
true,
224 ImGuiWindowFlags_NoScrollWithMouse);
230 if (ImGui::IsWindowHovered()) {
231 float wheel = ImGui::GetIO().MouseWheel;
234 }
else if (wheel < 0 &&
264 ImGui::BeginChild(
"##ExpandedMessageSettings", ImVec2(0, 100),
true,
265 ImGuiWindowFlags_AlwaysVerticalScrollbar);
266 ImGui::Text(
"Expanded Messages");
268 if (ImGui::Button(
"Load Expanded Message")) {
277 popup_manager->Show(
"Error");
286 if (ImGui::Button(
"Add New Message")) {
294 if (ImGui::Button(
"Save Expanded Messages")) {
304 if (ImGui::Button(
"Save As...")) {
313 if (ImGui::Button(
"Export to JSON")) {
325 ImGui::BeginChild(
"##TextCommands",
326 ImVec2(0, ImGui::GetContentRegionAvail().y / 2),
true,
327 ImGuiWindowFlags_AlwaysVerticalScrollbar);
328 static uint8_t command_parameter = 0;
330 for (
const auto& text_element : TextCommands) {
331 if (Button(text_element.GenericToken.c_str())) {
333 text_element.GetParamToken(command_parameter));
336 TextWrapped(
"%s", text_element.Description.c_str());
343 ImGui::BeginChild(
"##SpecialChars",
344 ImVec2(0, ImGui::GetContentRegionAvail().y / 2),
true,
345 ImGuiWindowFlags_AlwaysVerticalScrollbar);
346 for (
const auto& text_element : SpecialChars) {
347 if (Button(text_element.GenericToken.c_str())) {
351 TextWrapped(
"%s", text_element.Description.c_str());
358 if (ImGui::BeginChild(
"##DictionaryChild",
359 ImVec2(0, ImGui::GetContentRegionAvail().y),
true,
360 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
362 TableSetupColumn(
"ID");
363 TableSetupColumn(
"Contents");
369 Text(
"%s", dictionary.Contents.c_str());
383 LOG_WARN(
"MessageEditor",
"Preview data is empty, skipping bitmap update");
394 LOG_ERROR(
"MessageEditor",
"Bitmap surface is null after set_data()");
404 "Updated message preview bitmap (size: %zu) and queued texture update",
416 "Created message preview bitmap (%dx%d) with 8-bit depth and "
417 "queued texture creation",
423 std::vector<uint8_t> backup =
rom()->
vector();
431 bool in_second_bank =
false;
434 for (
const auto value : message.Data) {
441 return absl::InternalError(DisplayTextOverflowError(pos,
true));
446 in_second_bank =
true;
458 std::copy(backup.begin(), backup.end(),
rom()->mutable_data());
459 return absl::InternalError(DisplayTextOverflowError(pos,
false));
464 return absl::OkStatus();
469 return absl::InvalidArgumentError(
"No path specified for expanded messages");
501 std::copy(expanded_message.Data.begin(), expanded_message.Data.end(),
516 return absl::OkStatus();
525 return absl::OkStatus();
530 if (ImGui::GetClipboardText() !=
nullptr) {
534 return absl::OkStatus();
543 return absl::OkStatus();
555 return absl::OkStatus();
561 return absl::OkStatus();
584 if (ImGui::Begin(
"Find Text",
nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
585 static char find_text[256] =
"";
586 ImGui::InputText(
"Search", find_text, IM_ARRAYSIZE(find_text));
588 if (ImGui::Button(
"Find Next")) {
593 if (ImGui::Button(
"Find All")) {
598 if (ImGui::Button(
"Replace")) {
608 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