yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
message_editor.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_MESSAGE_EDITOR_H
2#define YAZE_APP_EDITOR_MESSAGE_EDITOR_H
3
4#include <array>
5#include <cstdint>
6#include <filesystem>
7#include <optional>
8#include <string>
9#include <string_view>
10#include <utility>
11#include <vector>
12
13#include "absl/status/status.h"
14#include "absl/status/statusor.h"
15#include "app/editor/editor.h"
20#include "app/gfx/core/bitmap.h"
23#include "app/gui/core/style.h"
24#include "rom/rom.h"
25
26namespace yaze {
27namespace editor {
28
29class AuthoringSaveWorkflowTestPeer;
30class MessageEditorTestPeer;
31class MessageEditorSaveTestPeer;
32class MessageEditorPublishGuardTestPeer;
33class MessageEditorListPanelTestPeer;
34
35constexpr int kGfxFont = 0x70000; // 2bpp format
36constexpr int kCharactersWidth = 0x74ADF;
37constexpr int kNumMessages = 396;
38constexpr int kFontGfxMessageSize = 128;
39constexpr int kFontGfxMessageDepth =
40 8; // Fixed: Must be 8 for indexed palette mode
41constexpr int kFontGfx16Size = 172 * 4096;
42
43constexpr uint8_t kBlockTerminator = 0x80;
44constexpr uint8_t kMessageBankChangeId = 0x80;
45
46class MessageEditor : public Editor {
47 public:
48 explicit MessageEditor(Rom* rom = nullptr) : rom_(rom) {
50 }
51
52 explicit MessageEditor(Rom* rom, const EditorDependencies& deps)
54 dependencies_ = deps;
55 }
56
57 void Initialize() override;
58 absl::Status Load() override;
59 absl::Status Update() override;
61
62 void DrawMessageList();
63 void DrawCurrentMessage();
64 void DrawFontAtlas();
65 void DrawTextCommands();
68 void DrawDictionary();
69 void DrawMessageTools();
70 void DrawMessagePreview();
71 void UpdateCurrentMessageFromText(const std::string& text);
72 void ContributeStatus(StatusBar* status_bar) override;
73
74 // Jump/navigation helper used by panels (e.g. Story Event Graph).
75 // Accepts vanilla IDs (0..N) and expanded IDs (expanded_base_id..).
76 bool OpenMessageById(int display_id);
77
78 absl::Status Save() override;
79 absl::Status BeginSaveTransaction() override;
80 void RollbackSaveTransaction() override;
81 void CommitSaveTransaction() override;
82 absl::Status SaveExpandedMessages();
83 absl::Status LoadExpandedMessagesFromRom();
84 absl::Status LoadCanonicalExpandedSource();
87
88 absl::Status Cut() override;
89 absl::Status Copy() override;
90 absl::Status Paste() override;
91 absl::Status Undo() override;
92 absl::Status Redo() override;
93 absl::Status Find() override;
94 // A pending text edit is committed to history by Undo(), so it counts.
95 bool CanUndo() const override {
96 return pending_undo_before_.has_value() || undo_manager_.CanUndo();
97 }
98 bool CanFind() const override { return true; }
99 void Delete();
100 void SelectAll();
101
102 void set_rom(Rom* rom) { rom_ = rom; }
103 Rom* rom() const { return rom_; }
104
105 private:
111
112 enum class SaveDomain {
116 };
117
120 uint32_t start;
121 std::vector<uint8_t> bytes;
122
123 uint32_t end() const { return start + static_cast<uint32_t>(bytes.size()); }
124 };
125
126 struct SavePlan {
127 std::vector<PlannedWrite> writes;
129 bool saves_font_widths = false;
132 };
133
134 struct DirtyState {
135 bool font_widths = false;
136 bool vanilla_messages = false;
137 bool expanded_messages = false;
138 };
139
140 absl::StatusOr<SavePlan> BuildSavePlan(bool include_font_widths,
141 bool include_vanilla_messages,
142 bool include_expanded_messages) const;
143 absl::Status ValidateSavePlan(const SavePlan& plan) const;
144 absl::Status ApplySavePlan(const SavePlan& plan);
145 absl::Status SaveDirtyDomains(bool include_font_widths,
146 bool include_vanilla_messages,
147 bool include_expanded_messages);
148 void MarkDomainDirty(SaveDomain domain);
149 void RecordSavedDomains(const SavePlan& plan);
150 void ClearSavedDomains(const DirtyState& saved);
152
153 bool case_sensitive_ = false;
154 bool match_whole_word_ = false;
155 std::string search_text_;
156 std::string replace_text_;
157 std::string replace_status_;
159 std::string list_filter_;
160 std::string command_filter_;
161 std::string symbol_filter_;
163 std::vector<std::string> baseline_messages_;
165 bool show_reference_ = true;
167 bool source_sync_ready_ = false;
176 bool find_panel_open_ = false;
177 bool find_focus_search_ = false;
178 bool find_has_match_ = false;
184 float editor_pane_height_ = 180.0f;
186
187 struct MessageRow {
188 int display_id = 0;
189 bool expanded = false;
190 uint32_t address = 0;
191 };
192
193 std::vector<MessageRow> CollectMessageRows(bool apply_filter) const;
194 int CurrentDisplayId() const;
195 std::string_view ContentsForDisplayId(int display_id) const;
196 void DrawFindBar();
197 void DrawMessageHeader();
199 void DrawTokenInserter(const std::vector<TextElement>& elements,
200 std::string& filter, bool use_parameter);
201 void InsertTokenAtCursor(const std::string& token);
202 void SelectAdjacentMessage(int delta);
203 void NoteLoadedMessages();
205 std::string CurrentReferenceText() const;
206 void DrawDialogueTextPane(float height);
207 bool HasMessageSourceLayout() const;
208 bool ExpandedEditsAreSourceOwned() const;
209 std::pair<int, int> ExpandedInspectionRange() const;
210 std::string MessageSourceIncomingPath() const;
212 absl::StatusOr<std::filesystem::path> ResolveCanonicalBundlePath() const;
213 absl::StatusOr<std::string> HashFileSha256(
214 const std::filesystem::path& path) const;
215 bool IsCanonicalBundlePath(const std::string& path) const;
217 std::vector<MessageData> messages;
218 std::vector<MessageData> vanilla_messages;
219 std::vector<std::string> parsed_messages;
220 int base_id = 0;
221 std::string path;
222 bool expanded_dirty = false;
223 bool vanilla_dirty = false;
225 bool preview_ready = false;
226 bool preview_changed = false;
228 std::string preview_draft_sha;
229 std::string preview_summary;
230 std::string preview_status;
232 };
234 void RestoreExpandedDraft(const ExpandedDraftSnapshot& snapshot);
235 absl::Status LoadExpandedMessagesFromBin(const std::string& path);
239 bool preview_disabled = false;
240 bool publish_disabled = false;
241 };
244 bool AdvanceFind(bool forward);
245 bool ActivateFindMatch(const MessageRow& row, size_t offset, bool wrapped);
248
249 // Replace helpers
251 int ReplaceAllMatches();
252
253 std::array<uint8_t, 0x4000> raw_font_gfx_data_;
254 std::vector<std::string> parsed_messages_;
255 std::vector<MessageData> list_of_texts_;
256 std::vector<MessageData> expanded_messages_;
257
260
264
265 gui::Canvas font_gfx_canvas_{"##FontGfxCanvas", ImVec2(256, 256)};
267 ImVec2(172 * 2, 4096)};
280
281 // Undo/Redo - delegates to UndoManager (inherited from Editor)
282 std::optional<MessageSnapshot> pending_undo_before_;
283 void PushUndoSnapshot();
284 void FinalizePendingUndo();
285 void ApplySnapshot(const MessageSnapshot& snapshot);
286
287 // Panel visibility states
288 bool show_message_list_ = false;
290 bool show_font_atlas_ = false;
291 bool show_dictionary_ = false;
292
293 void ResolveFontPalette();
295 void LoadFontGraphics();
296 void RefreshFontAtlasBitmap(const std::vector<uint8_t>& font_data);
297 void ApplyFontPalette();
299 void ImportMessageBundleFromFile(const std::string& path);
301
305 std::vector<std::string> current_parse_errors_;
306 std::vector<std::string> current_parse_warnings_;
307};
308
309} // namespace editor
310} // namespace yaze
311
312#endif // YAZE_APP_EDITOR_MESSAGE_EDITOR_H
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:52
Interface for editor classes.
Definition editor.h:252
UndoManager undo_manager_
Definition editor.h:383
zelda3::GameData * game_data() const
Definition editor.h:369
EditorDependencies dependencies_
Definition editor.h:382
EditorType type_
Definition editor.h:381
MessageSourcePublishButtons DrawMessageSourcePublishButtons()
std::vector< std::string > baseline_messages_
void RestoreExpandedDraft(const ExpandedDraftSnapshot &snapshot)
std::vector< std::string > parsed_messages_
absl::Status Copy() override
void CommitSaveTransaction() override
std::vector< MessageData > expanded_messages_
void ContributeStatus(StatusBar *status_bar) override
absl::Status Find() override
void DrawTokenInserter(const std::vector< TextElement > &elements, std::string &filter, bool use_parameter)
void RollbackSaveTransaction() override
absl::Status Update() override
void ClearSavedDomains(const DirtyState &saved)
bool IsCanonicalBundlePath(const std::string &path) const
absl::Status LoadExpandedMessagesFromRom()
void RecordSavedDomains(const SavePlan &plan)
void DrawDialogueTextPane(float height)
void UpdateCurrentMessageFromText(const std::string &text)
absl::Status Paste() override
void ApplySnapshot(const MessageSnapshot &snapshot)
absl::StatusOr< SavePlan > BuildSavePlan(bool include_font_widths, bool include_vanilla_messages, bool include_expanded_messages) const
std::vector< int > transaction_expanded_address_snapshot_
bool AdvanceFind(bool forward)
ExpandedDraftSnapshot CaptureExpandedDraft() const
void MarkDomainDirty(SaveDomain domain)
void RefreshFontAtlasBitmap(const std::vector< uint8_t > &font_data)
bool HasUnpublishedMessageSourceChanges() const
absl::StatusOr< std::filesystem::path > ResolveCanonicalBundlePath() const
std::vector< std::string > current_parse_errors_
absl::Status Undo() override
absl::Status Load() override
std::string MessageSourceIncomingPath() const
absl::Status LoadExpandedMessagesFromBin(const std::string &path)
absl::StatusOr< std::string > HashFileSha256(const std::filesystem::path &path) const
std::vector< std::string > current_parse_warnings_
std::array< uint8_t, 0x4000 > raw_font_gfx_data_
gfx::SnesPalette BuildFallbackFontPalette() const
std::pair< int, int > ExpandedInspectionRange() const
bool CanUndo() const override
bool CanFind() const override
friend class MessageEditorPublishGuardTestPeer
MessageEditor(Rom *rom=nullptr)
absl::Status SaveDirtyDomains(bool include_font_widths, bool include_vanilla_messages, bool include_expanded_messages)
absl::Status Cut() override
absl::Status LoadCanonicalExpandedSource()
void InsertTokenAtCursor(const std::string &token)
std::vector< MessageRow > CollectMessageRows(bool apply_filter) const
MessageEditor(Rom *rom, const EditorDependencies &deps)
bool ActivateFindMatch(const MessageRow &row, size_t offset, bool wrapped)
std::optional< MessageSnapshot > pending_undo_before_
absl::Status BeginSaveTransaction() override
std::string_view ContentsForDisplayId(int display_id) const
std::vector< MessageData > list_of_texts_
std::string CurrentReferenceText() const
friend class AuthoringSaveWorkflowTestPeer
friend class MessageEditorListPanelTestPeer
bool OpenMessageById(int display_id)
gfx::SnesPalette font_preview_colors_
absl::Status Redo() override
void SelectAdjacentMessage(int delta)
void ImportMessageBundleFromFile(const std::string &path)
absl::Status ValidateSavePlan(const SavePlan &plan) const
absl::Status ApplySavePlan(const SavePlan &plan)
absl::Status Save() override
void SetGameData(zelda3::GameData *game_data) override
A session-aware status bar displayed at the bottom of the application.
Definition status_bar.h:57
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
Modern, robust canvas for drawing and manipulating graphics.
Definition canvas.h:64
constexpr int kCharactersWidth
constexpr int kFontGfx16Size
constexpr uint8_t kBlockTerminator
constexpr int kGfxFont
constexpr int kFontGfxMessageSize
constexpr int kFontGfxMessageDepth
constexpr uint8_t kMessageBankChangeId
constexpr int kNumMessages
Unified dependency container for all editor types.
Definition editor.h:170
std::vector< PlannedWrite > writes