add text commands column to message editor

This commit is contained in:
scawful
2024-07-28 11:33:01 -04:00
parent 11199838fc
commit 6ac160207d
2 changed files with 128 additions and 139 deletions

View File

@@ -26,12 +26,14 @@ namespace app {
namespace editor { namespace editor {
using ImGui::Begin; using ImGui::Begin;
using ImGui::BeginChild;
using ImGui::BeginTable; using ImGui::BeginTable;
using ImGui::Button; using ImGui::Button;
using ImGui::End; using ImGui::End;
using ImGui::EndChild; using ImGui::EndChild;
using ImGui::EndTable; using ImGui::EndTable;
using ImGui::InputText; using ImGui::InputText;
using ImGui::InputTextMultiline;
using ImGui::SameLine; using ImGui::SameLine;
using ImGui::Separator; using ImGui::Separator;
using ImGui::TableHeadersRow; using ImGui::TableHeadersRow;
@@ -121,13 +123,17 @@ absl::Status MessageEditor::Update() {
if (rom()->is_loaded() && !data_loaded_) { if (rom()->is_loaded() && !data_loaded_) {
RETURN_IF_ERROR(rom()->LoadFontGraphicsData()) RETURN_IF_ERROR(rom()->LoadFontGraphicsData())
RETURN_IF_ERROR(Initialize()); RETURN_IF_ERROR(Initialize());
CurrentMessage = ListOfTexts[1];
data_loaded_ = true; data_loaded_ = true;
} }
if (BeginTable("##MessageEditor", 2, if (BeginTable("##MessageEditor", 3,
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable)) { ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable)) {
TableSetupColumn("##ListOfMessages"); TableSetupColumn("List");
TableSetupColumn("##MessageEditorColumn2"); TableSetupColumn("Contents");
TableSetupColumn("Commands");
TableHeadersRow();
TableNextColumn(); TableNextColumn();
DrawMessageList(); DrawMessageList();
@@ -135,6 +141,9 @@ absl::Status MessageEditor::Update() {
TableNextColumn(); TableNextColumn();
DrawCurrentMessage(); DrawCurrentMessage();
TableNextColumn();
DrawTextCommands();
EndTable(); EndTable();
} }
@@ -142,24 +151,41 @@ absl::Status MessageEditor::Update() {
} }
void MessageEditor::DrawMessageList() { void MessageEditor::DrawMessageList() {
for (const auto& message : ListOfTexts) { if (InputText("Search", &search_text_)) {
TextWrapped("%s", absl::StrCat("Message ", message.RawString).c_str()); DisplayedMessages.clear();
SameLine(); for (const auto& message : ListOfTexts) {
if (Button(absl::StrCat("Message ", message.ID).c_str())) { if (absl::StrContains(message.ContentsParsed, search_text_)) {
SelectMessageID(message.ID); DisplayedMessages.push_back(message);
}
} }
} }
if (BeginChild("##MessagesList", ImVec2(0, 0), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
for (const auto& message : ListOfTexts) {
if (Button(core::UppercaseHexWord(message.ID).c_str())) {
CurrentMessage = message;
}
SameLine();
TextWrapped("%s", ParsedMessages[message.ID].c_str());
Separator();
}
EndChild();
}
} }
void MessageEditor::DrawCurrentMessage() { void MessageEditor::DrawCurrentMessage() {
TextWrapped("%s", absl::StrCat("Message ", CurrentMessage.RawString).c_str()); Button(absl::StrCat("Message ", CurrentMessage.ID).c_str());
SameLine(); if (InputTextMultiline("##MessageEditor", &ParsedMessages[CurrentMessage.ID],
if (Button(absl::StrCat("Message ", CurrentMessage.ID).c_str())) { ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
SelectMessageID(CurrentMessage.ID); CurrentMessage.Data = ParseMessageToData(message_text_box_.text);
DrawMessagePreview();
} }
Separator(); Separator();
ImGui::BeginChild("MessageEditorCanvas", ImVec2(0, 0), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar); Text("Font Graphics");
BeginChild("MessageEditorCanvas", ImVec2(0, 128), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar);
font_gfx_canvas_.DrawBackground(); font_gfx_canvas_.DrawBackground();
font_gfx_canvas_.DrawContextMenu(); font_gfx_canvas_.DrawContextMenu();
font_gfx_canvas_.DrawBitmap(font_gfx_bitmap_, 0, 0); font_gfx_canvas_.DrawBitmap(font_gfx_bitmap_, 0, 0);
@@ -167,8 +193,10 @@ void MessageEditor::DrawCurrentMessage() {
font_gfx_canvas_.DrawOverlay(); font_gfx_canvas_.DrawOverlay();
EndChild(); EndChild();
Separator(); Separator();
ImGui::BeginChild("CurrentGfxFont", ImVec2(0, 0), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar); Text("Message Preview");
BeginChild("CurrentGfxFont", ImVec2(0, 0), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar);
current_font_gfx16_canvas_.DrawBackground(); current_font_gfx16_canvas_.DrawBackground();
current_font_gfx16_canvas_.DrawContextMenu(); current_font_gfx16_canvas_.DrawContextMenu();
current_font_gfx16_canvas_.DrawBitmap(current_font_gfx16_bitmap_, 0, 0); current_font_gfx16_canvas_.DrawBitmap(current_font_gfx16_bitmap_, 0, 0);
@@ -178,22 +206,35 @@ void MessageEditor::DrawCurrentMessage() {
Separator(); Separator();
} }
void MessageEditor::DrawTextCommands() {
if (BeginChild("##TextCommands", ImVec2(0, 0), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
for (const auto& text_element : TextCommands) {
if (Button(text_element.GenericToken.c_str())) {
}
SameLine();
TextWrapped("%s", text_element.Description.c_str());
Separator();
}
EndChild();
}
}
absl::Status MessageEditor::Initialize() { absl::Status MessageEditor::Initialize() {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
width_array[i] = rom()->data()[kCharactersWidth + i]; width_array[i] = rom()->data()[kCharactersWidth + i];
} }
previewColors.AddColor(0x7FFF); // White font_preview_colors_.AddColor(0x7FFF); // White
previewColors.AddColor(0x7C00); // Red font_preview_colors_.AddColor(0x7C00); // Red
previewColors.AddColor(0x03E0); // Green font_preview_colors_.AddColor(0x03E0); // Green
previewColors.AddColor(0x001F); // Blue font_preview_colors_.AddColor(0x001F); // Blue
fontgfx16Ptr = rom()->font_gfx_data(); fontgfx16Ptr = rom()->font_gfx_data();
// 4bpp // 4bpp
font_gfx_bitmap_.Create(128, 128, 64, gfx::kFormat4bppIndexed, fontgfx16Ptr); RETURN_IF_ERROR(rom()->CreateAndRenderBitmap(
RETURN_IF_ERROR(rom()->CreateAndRenderBitmap(128, 128, 64, fontgfx16Ptr, 128, 128, 64, fontgfx16Ptr, font_gfx_bitmap_, font_preview_colors_))
font_gfx_bitmap_, previewColors))
currentfontgfx16Ptr.reserve(172 * 4096); currentfontgfx16Ptr.reserve(172 * 4096);
for (int i = 0; i < 172 * 4096; i++) { for (int i = 0; i < 172 * 4096; i++) {
@@ -201,22 +242,13 @@ absl::Status MessageEditor::Initialize() {
} }
// 8bpp // 8bpp
current_font_gfx16_bitmap_.Create(172, 4096, 172, gfx::kFormat8bppIndexed, RETURN_IF_ERROR(rom()->CreateAndRenderBitmap(
currentfontgfx16Ptr); 172, 4096, 172, currentfontgfx16Ptr, current_font_gfx16_bitmap_,
RETURN_IF_ERROR( font_preview_colors_))
rom()->CreateAndRenderBitmap(172, 4096, 172, currentfontgfx16Ptr,
current_font_gfx16_bitmap_, previewColors))
// auto previewColors = new Color[]{
// Color.DimGray,
// Color.DarkBlue,
// Color.White,
// Color.DarkOrange,
// };
gfx::SnesPalette color_palette = font_gfx_bitmap_.palette(); gfx::SnesPalette color_palette = font_gfx_bitmap_.palette();
for (int i = 0; i < previewColors.size(); i++) { for (int i = 0; i < font_preview_colors_.size(); i++) {
*color_palette.mutable_color(i) = previewColors[i]; *color_palette.mutable_color(i) = font_preview_colors_[i];
} }
*font_gfx_bitmap_.mutable_palette() = color_palette; *font_gfx_bitmap_.mutable_palette() = color_palette;
@@ -224,25 +256,39 @@ absl::Status MessageEditor::Initialize() {
BuildDictionaryEntries(); BuildDictionaryEntries();
ReadAllTextData(); ReadAllTextData();
// foreach (MessageData messageData in for (const auto& message : ListOfTexts) {
// ListOfTexts) { DisplayedMessages.push_back(message);
// DisplayedMessages.push_back(messageData); }
// }
// textListbox.BeginUpdate();
// textListbox.DataSource =
// DisplayedMessages;
// textListbox.EndUpdate();
// textListbox.DisplayMember = "Text";
// pictureBox2.Refresh();
// SelectedTileID.Text =
// selected_tile.ToString("X2");
// SelectedTileASCII.Text =
// ParseTextDataByte((uint8_t)selected_tile);
// CreateFontGfxData(rom()->data()); // CreateFontGfxData(rom()->data());
for (const auto& each_message : ListOfTexts) {
// Each string has a [:XX] char encoded
// The corresponding character is found in CharEncoder unordered_map
std::string parsed_message = "";
for (const auto& byte : each_message.Data) {
// Find the char byte in the CharEncoder map
if (CharEncoder.contains(byte)) {
parsed_message.push_back(CharEncoder.at(byte));
} else {
// If the byte is not found in the CharEncoder map, it is a command
// or a dictionary entry
if (byte >= DICTOFF && byte < (DICTOFF + 97)) {
// Dictionary entry
auto dictionaryEntry = GetDictionaryFromID(byte - DICTOFF);
parsed_message.append(dictionaryEntry.Contents);
} else {
// Command
TextElement textElement = FindMatchingCommand(byte);
if (!textElement.Empty()) {
parsed_message.append(textElement.GenericToken);
}
}
}
}
ParsedMessages.push_back(parsed_message);
}
return absl::OkStatus(); return absl::OkStatus();
} }
@@ -276,7 +322,7 @@ void MessageEditor::BuildDictionaryEntries() {
void MessageEditor::ReadAllTextData() { void MessageEditor::ReadAllTextData() {
int messageID = 0; int messageID = 0;
uint8_t value; uint8_t current_byte;
int pos = kTextData; int pos = kTextData;
std::vector<uint8_t> temp_bytes_raw; std::vector<uint8_t> temp_bytes_raw;
std::vector<uint8_t> temp_bytes_parsed; std::vector<uint8_t> temp_bytes_parsed;
@@ -286,9 +332,9 @@ void MessageEditor::ReadAllTextData() {
TextElement textElement; TextElement textElement;
while (true) { while (true) {
value = rom()->data()[pos++]; current_byte = rom()->data()[pos++];
if (value == MESSAGETERMINATOR) { if (current_byte == MESSAGETERMINATOR) {
auto message = auto message =
MessageData(messageID++, pos, current_message_raw, temp_bytes_raw, MessageData(messageID++, pos, current_message_raw, temp_bytes_raw,
current_message_parsed, temp_bytes_parsed); current_message_parsed, temp_bytes_parsed);
@@ -301,25 +347,25 @@ void MessageEditor::ReadAllTextData() {
current_message_parsed.clear(); current_message_parsed.clear();
continue; continue;
} else if (value == 0xFF) { } else if (current_byte == 0xFF) {
break; break;
} }
temp_bytes_raw.push_back(value); temp_bytes_raw.push_back(current_byte);
// Check for command. // Check for command.
textElement = FindMatchingCommand(value); textElement = FindMatchingCommand(current_byte);
if (!textElement.Empty()) { if (!textElement.Empty()) {
temp_bytes_parsed.push_back(value); temp_bytes_parsed.push_back(current_byte);
if (textElement.HasArgument) { if (textElement.HasArgument) {
value = rom()->data()[pos++]; current_byte = rom()->data()[pos++];
temp_bytes_raw.push_back(value); temp_bytes_raw.push_back(current_byte);
temp_bytes_parsed.push_back(value); temp_bytes_parsed.push_back(current_byte);
} }
current_message_raw.append(textElement.GetParameterizedToken(value)); current_message_raw.append(textElement.GetParameterizedToken(current_byte));
current_message_parsed.append(textElement.GetParameterizedToken(value)); current_message_parsed.append(textElement.GetParameterizedToken(current_byte));
if (textElement.Token == BANKToken) { if (textElement.Token == BANKToken) {
pos = kTextData2; pos = kTextData2;
@@ -329,17 +375,17 @@ void MessageEditor::ReadAllTextData() {
} }
// Check for special characters. // Check for special characters.
textElement = FindMatchingSpecial(value); textElement = FindMatchingSpecial(current_byte);
if (!textElement.Empty()) { if (!textElement.Empty()) {
current_message_raw.append(textElement.GetParameterizedToken()); current_message_raw.append(textElement.GetParameterizedToken());
current_message_parsed.append(textElement.GetParameterizedToken()); current_message_parsed.append(textElement.GetParameterizedToken());
temp_bytes_parsed.push_back(value); temp_bytes_parsed.push_back(current_byte);
continue; continue;
} }
// Check for dictionary. // Check for dictionary.
int dictionary = FindDictionaryEntry(value); int dictionary = FindDictionaryEntry(current_byte);
if (dictionary >= 0) { if (dictionary >= 0) {
current_message_raw.append("["); current_message_raw.append("[");
@@ -362,16 +408,14 @@ void MessageEditor::ReadAllTextData() {
} }
// Everything else. // Everything else.
if (CharEncoder.contains(value)) { if (CharEncoder.contains(current_byte)) {
std::string str = ""; std::string str = "";
str.push_back(CharEncoder.at(value)); str.push_back(CharEncoder.at(current_byte));
current_message_raw.append(str); current_message_raw.append(str);
current_message_parsed.append(str); current_message_parsed.append(str);
temp_bytes_parsed.push_back(value); temp_bytes_parsed.push_back(current_byte);
} }
} }
// 00074703
} }
absl::Status MessageEditor::Cut() { absl::Status MessageEditor::Cut() {
@@ -508,14 +552,6 @@ uint8_t MessageEditor::FindMatchingCharacter(char value) {
return 0xFF; return 0xFF;
} }
bool MessageEditor::SelectMessageID(int id) {
// if (id < textListbox.Items.size()) {
// textListbox.SelectedIndex = id;
// return true;
// }
return false;
}
string MessageEditor::ParseTextDataByte(uint8_t value) { string MessageEditor::ParseTextDataByte(uint8_t value) {
if (CharEncoder.contains(value)) { if (CharEncoder.contains(value)) {
char c = CharEncoder.at(value); char c = CharEncoder.at(value);

View File

@@ -380,54 +380,6 @@ class MessageEditor : public Editor, public SharedRom {
} }
}; };
class TextMessageElement {
private:
std::string Token;
std::string Pattern;
std::string StrictPattern;
std::string Description;
bool HasArgument;
uint8_t ID;
std::string GenericToken;
public:
TextMessageElement() = default;
TextMessageElement(uint8_t a, std::string t, bool arg, std::string d)
: Token(t), HasArgument(arg), Description(d), ID(a) {
Pattern =
arg ? absl::StrFormat(
"\\[%s:?([0-9A-F]{1,2})\\]",
std::regex_replace(
Token, std::regex("([][(){}.*+?^$|\\\\])"), R"(\$1)"))
: absl::StrFormat(
"\\[%s\\]",
std::regex_replace(
Token, std::regex("([][(){}.*+?^$|\\\\])"), R"(\$1)"));
StrictPattern = absl::StrFormat("^%s$", Pattern);
GenericToken = arg ? absl::StrFormat("[%s:##]", Token)
: absl::StrFormat("[%s]", Token);
}
std::string GetParameterizedToken(uint8_t b = 0) {
if (HasArgument) {
return absl::StrFormat("[%s:%00X]", Token, b);
} else {
return absl::StrFormat("[%s]", Token);
}
}
std::string ToString() {
return absl::StrFormat("%s %s", GenericToken, Description);
}
std::smatch MatchMe(std::string dfrag) {
std::regex re(StrictPattern);
std::smatch match;
std::regex_search(dfrag, match, re);
return match;
}
};
struct DictionaryEntry { struct DictionaryEntry {
uint8_t ID; uint8_t ID;
std::string Contents; std::string Contents;
@@ -457,17 +409,12 @@ class MessageEditor : public Editor, public SharedRom {
} }
}; };
MessageEditor() { MessageEditor() { type_ = EditorType::kMessage; }
type_ = EditorType::kMessage;
// TextCommandList.Items.AddRange(TextCommands);
// SpecialsList.Items.AddRange(SpecialChars);
// pictureBox1.MouseWheel += new
// MouseEventHandler(PictureBox1_MouseWheel);
}
absl::Status Update() override; absl::Status Update() override;
void DrawMessageList(); void DrawMessageList();
void DrawCurrentMessage(); void DrawCurrentMessage();
void DrawTextCommands();
absl::Status Initialize(); absl::Status Initialize();
void ReadAllTextData(); void ReadAllTextData();
@@ -492,7 +439,6 @@ class MessageEditor : public Editor, public SharedRom {
static uint8_t FindDictionaryEntry(uint8_t value); static uint8_t FindDictionaryEntry(uint8_t value);
static uint8_t FindMatchingCharacter(char value); static uint8_t FindMatchingCharacter(char value);
bool SelectMessageID(int id);
void DrawTileToPreview(int x, int y, int srcx, int srcy, int pal, void DrawTileToPreview(int x, int y, int srcx, int srcy, int pal,
bool mirror_x = false, bool mirror_y = false, bool mirror_x = false, bool mirror_y = false,
int sizex = 1, int sizey = 1); int sizex = 1, int sizey = 1);
@@ -518,14 +464,21 @@ class MessageEditor : public Editor, public SharedRom {
std::vector<MessageData> ListOfTexts; std::vector<MessageData> ListOfTexts;
std::vector<MessageData> DisplayedMessages; std::vector<MessageData> DisplayedMessages;
std::vector<std::string> ParsedMessages;
MessageData CurrentMessage; MessageData CurrentMessage;
private: private:
static const TextElement DictionaryElement; static const TextElement DictionaryElement;
bool data_loaded_ = false; bool data_loaded_ = false;
int current_message_id_ = 0;
std::string search_text_ = "";
gui::Canvas font_gfx_canvas_{"##FontGfxCanvas", ImVec2(128, 128)}; gui::Canvas font_gfx_canvas_{"##FontGfxCanvas", ImVec2(128, 128)};
gui::Canvas current_font_gfx16_canvas_; gui::Canvas current_font_gfx16_canvas_{"##CurrentMessageGfx",
ImVec2(128, 512)};
gfx::Bitmap font_gfx_bitmap_; gfx::Bitmap font_gfx_bitmap_;
gfx::Bitmap current_font_gfx16_bitmap_; gfx::Bitmap current_font_gfx16_bitmap_;