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"
30 std::string bankSTR = bank ?
"1st" :
"2nd";
32 bank ? absl::StrFormat(
"%X4", pos & 0xFFFF)
33 : absl::StrFormat(
"%X4", (pos -
kTextData2) & 0xFFFF);
34 std::string message = absl::StrFormat(
35 "There is too much text data in the %s block to save.\n"
36 "Available: %X4 | Used: %s",
37 bankSTR, space, posSTR);
43using ImGui::BeginChild;
44using ImGui::BeginTable;
48using ImGui::InputTextMultiline;
52using ImGui::Separator;
53using ImGui::TableHeadersRow;
54using ImGui::TableNextColumn;
55using ImGui::TableSetupColumn;
57using ImGui::TextWrapped;
60 ImGuiTableFlags_Borders |
61 ImGuiTableFlags_Resizable;
67 card_manager.RegisterCard({
68 .card_id =
"message.message_list",
69 .display_name =
"Message List",
71 .category =
"Message",
76 card_manager.RegisterCard({
77 .card_id =
"message.message_editor",
78 .display_name =
"Message Editor",
80 .category =
"Message",
85 card_manager.RegisterCard({
86 .card_id =
"message.font_atlas",
87 .display_name =
"Font Atlas",
89 .category =
"Message",
94 card_manager.RegisterCard({
95 .card_id =
"message.dictionary",
96 .display_name =
"Dictionary",
98 .category =
"Message",
111 for (
int i = 0; i < 0x4000; i++) {
126 LOG_INFO(
"MessageEditor",
"Font bitmap created and texture queued");
130 if (load_font.ok()) {
142 return absl::OkStatus();
147 TableSetupColumn(
"List");
148 TableSetupColumn(
"Contents");
149 TableSetupColumn(
"Font Atlas");
150 TableSetupColumn(
"Commands");
170 return absl::OkStatus();
175 if (BeginChild(
"##MessagesList", ImVec2(0, 0),
true,
176 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
179 TableSetupColumn(
"ID");
180 TableSetupColumn(
"Contents");
181 TableSetupColumn(
"Data");
201 PushID(expanded_message.ID + 0x18D);
202 if (Button(
util::HexWord(expanded_message.ID + 0x18D).c_str())) {
213 TextWrapped(
"%s",
util::HexLong(expanded_message.Address).c_str());
225 ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
228 temp.erase(std::remove(temp.begin(), temp.end(),
'\n'), temp.end());
235 ImGui::BeginChild(
"##MessagePreview", ImVec2(0, 0),
true, 1);
236 Text(
"Message Preview");
237 if (Button(
"View Palette")) {
238 ImGui::OpenPopup(
"Palette");
240 if (ImGui::BeginPopup(
"Palette")) {
245 BeginChild(
"CurrentGfxFont", ImVec2(348, 0),
true,
246 ImGuiWindowFlags_NoScrollWithMouse);
252 if (ImGui::IsWindowHovered()) {
253 float wheel = ImGui::GetIO().MouseWheel;
256 }
else if (wheel < 0 &&
286 ImGui::BeginChild(
"##ExpandedMessageSettings", ImVec2(0, 100),
true,
287 ImGuiWindowFlags_AlwaysVerticalScrollbar);
288 ImGui::Text(
"Expanded Messages");
289 static std::string expanded_message_path =
"";
290 if (ImGui::Button(
"Load Expanded Message")) {
292 if (!expanded_message_path.empty()) {
303 ImGui::Text(
"Expanded Path: %s", expanded_message_path.c_str());
305 if (ImGui::Button(
"Add New Message")) {
312 if (ImGui::Button(
"Save Expanded Messages")) {
321 ImGui::BeginChild(
"##TextCommands",
322 ImVec2(0, ImGui::GetContentRegionAvail().y / 2),
true,
323 ImGuiWindowFlags_AlwaysVerticalScrollbar);
324 static uint8_t command_parameter = 0;
326 for (
const auto& text_element : TextCommands) {
327 if (Button(text_element.GenericToken.c_str())) {
329 text_element.GetParamToken(command_parameter));
332 TextWrapped(
"%s", text_element.Description.c_str());
339 ImGui::BeginChild(
"##SpecialChars",
340 ImVec2(0, ImGui::GetContentRegionAvail().y / 2),
true,
341 ImGuiWindowFlags_AlwaysVerticalScrollbar);
342 for (
const auto& text_element : SpecialChars) {
343 if (Button(text_element.GenericToken.c_str())) {
347 TextWrapped(
"%s", text_element.Description.c_str());
354 if (ImGui::BeginChild(
"##DictionaryChild",
355 ImVec2(0, ImGui::GetContentRegionAvail().y),
true,
356 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
358 TableSetupColumn(
"ID");
359 TableSetupColumn(
"Contents");
365 Text(
"%s", dictionary.Contents.c_str());
379 LOG_WARN(
"MessageEditor",
"Preview data is empty, skipping bitmap update");
390 LOG_ERROR(
"MessageEditor",
"Bitmap surface is null after set_data()");
398 LOG_DEBUG(
"MessageEditor",
"Updated message preview bitmap (size: %zu) and queued texture update",
408 LOG_INFO(
"MessageEditor",
"Created message preview bitmap (%dx%d) and queued texture creation",
414 std::vector<uint8_t> backup =
rom()->
vector();
422 bool in_second_bank =
false;
425 for (
const auto value : message.Data) {
432 return absl::InternalError(DisplayTextOverflowError(pos,
true));
437 in_second_bank =
true;
449 std::copy(backup.begin(), backup.end(),
rom()->mutable_data());
450 return absl::InternalError(DisplayTextOverflowError(pos,
false));
455 return absl::OkStatus();
460 std::copy(expanded_message.Data.begin(), expanded_message.Data.end(),
468 return absl::OkStatus();
477 return absl::OkStatus();
482 if (ImGui::GetClipboardText() !=
nullptr) {
486 return absl::OkStatus();
495 return absl::OkStatus();
507 return absl::OkStatus();
513 return absl::OkStatus();
536 if (ImGui::Begin(
"Find Text",
nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
537 static char find_text[256] =
"";
538 ImGui::InputText(
"Search", find_text, IM_ARRAYSIZE(find_text));
540 if (ImGui::Button(
"Find Next")) {
545 if (ImGui::Button(
"Find All")) {
550 if (ImGui::Button(
"Replace")) {
560 return absl::OkStatus();
auto palette_group() const
absl::Status WriteByte(int addr, uint8_t value)
absl::Status SaveToFile(const SaveSettings &settings)
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
bool show_message_editor_
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_
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.
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 EditorCardManager & Get()
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
#define ICON_MD_FONT_DOWNLOAD
#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)
#define RETURN_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)
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)
Main namespace for the application.
absl::StatusOr< gfx::Bitmap > LoadFontGraphics(const Rom &rom)
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_