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();
86
87 absl::Status Cut() override;
88 absl::Status Copy() override;
89 absl::Status Paste() override;
90 absl::Status Undo() override;
91 absl::Status Redo() override;
92 absl::Status Find() override;
93 // A pending text edit is committed to history by Undo(), so it counts.
94 bool CanUndo() const override {
95 return pending_undo_before_.has_value() || undo_manager_.CanUndo();
96 }
97 bool CanFind() const override { return true; }
98 void Delete();
99 void SelectAll();
100
101 void set_rom(Rom* rom) { rom_ = rom; }
102 Rom* rom() const { return rom_; }
103
104 private:
110
111 enum class SaveDomain {
115 };
116
119 uint32_t start;
120 std::vector<uint8_t> bytes;
121
122 uint32_t end() const { return start + static_cast<uint32_t>(bytes.size()); }
123 };
124
125 struct SavePlan {
126 std::vector<PlannedWrite> writes;
128 bool saves_font_widths = false;
131 };
132
133 struct DirtyState {
134 bool font_widths = false;
135 bool vanilla_messages = false;
136 bool expanded_messages = false;
137 };
138
139 absl::StatusOr<SavePlan> BuildSavePlan(bool include_font_widths,
140 bool include_vanilla_messages,
141 bool include_expanded_messages) const;
142 absl::Status ValidateSavePlan(const SavePlan& plan) const;
143 absl::Status ApplySavePlan(const SavePlan& plan);
144 absl::Status SaveDirtyDomains(bool include_font_widths,
145 bool include_vanilla_messages,
146 bool include_expanded_messages);
147 void MarkDomainDirty(SaveDomain domain);
148 void RecordSavedDomains(const SavePlan& plan);
149 void ClearSavedDomains(const DirtyState& saved);
151
152 bool case_sensitive_ = false;
153 bool match_whole_word_ = false;
154 std::string search_text_;
155 std::string replace_text_;
156 std::string replace_status_;
158 std::string list_filter_;
159 std::string command_filter_;
160 std::string symbol_filter_;
162 std::vector<std::string> baseline_messages_;
164 bool show_reference_ = true;
166 bool source_sync_ready_ = false;
175 bool find_panel_open_ = false;
176 bool find_focus_search_ = false;
177 bool find_has_match_ = false;
183 float editor_pane_height_ = 180.0f;
185
186 struct MessageRow {
187 int display_id = 0;
188 bool expanded = false;
189 uint32_t address = 0;
190 };
191
192 std::vector<MessageRow> CollectMessageRows(bool apply_filter) const;
193 int CurrentDisplayId() const;
194 std::string_view ContentsForDisplayId(int display_id) const;
195 void DrawFindBar();
196 void DrawMessageHeader();
198 void DrawTokenInserter(const std::vector<TextElement>& elements,
199 std::string& filter, bool use_parameter);
200 void InsertTokenAtCursor(const std::string& token);
201 void SelectAdjacentMessage(int delta);
202 void NoteLoadedMessages();
204 std::string CurrentReferenceText() const;
205 void DrawDialogueTextPane(float height);
206 bool HasMessageSourceLayout() const;
207 bool ExpandedEditsAreSourceOwned() const;
208 std::pair<int, int> ExpandedInspectionRange() const;
209 std::string MessageSourceIncomingPath() const;
211 absl::StatusOr<std::filesystem::path> ResolveCanonicalBundlePath() const;
212 absl::StatusOr<std::string> HashFileSha256(
213 const std::filesystem::path& path) const;
214 bool IsCanonicalBundlePath(const std::string& path) const;
216 std::vector<MessageData> messages;
217 std::vector<MessageData> vanilla_messages;
218 std::vector<std::string> parsed_messages;
219 int base_id = 0;
220 std::string path;
221 bool expanded_dirty = false;
222 bool vanilla_dirty = false;
224 bool preview_ready = false;
225 bool preview_changed = false;
227 std::string preview_draft_sha;
228 std::string preview_summary;
229 std::string preview_status;
231 };
233 void RestoreExpandedDraft(const ExpandedDraftSnapshot& snapshot);
234 absl::Status LoadExpandedMessagesFromBin(const std::string& path);
238 bool preview_disabled = false;
239 bool publish_disabled = false;
240 };
243 bool AdvanceFind(bool forward);
244 bool ActivateFindMatch(const MessageRow& row, size_t offset, bool wrapped);
247
248 // Replace helpers
250 int ReplaceAllMatches();
251
252 std::array<uint8_t, 0x4000> raw_font_gfx_data_;
253 std::vector<std::string> parsed_messages_;
254 std::vector<MessageData> list_of_texts_;
255 std::vector<MessageData> expanded_messages_;
256
259
263
264 gui::Canvas font_gfx_canvas_{"##FontGfxCanvas", ImVec2(256, 256)};
266 ImVec2(172 * 2, 4096)};
279
280 // Undo/Redo - delegates to UndoManager (inherited from Editor)
281 std::optional<MessageSnapshot> pending_undo_before_;
282 void PushUndoSnapshot();
283 void FinalizePendingUndo();
284 void ApplySnapshot(const MessageSnapshot& snapshot);
285
286 // Panel visibility states
287 bool show_message_list_ = false;
289 bool show_font_atlas_ = false;
290 bool show_dictionary_ = false;
291
292 void ResolveFontPalette();
294 void LoadFontGraphics();
295 void RefreshFontAtlasBitmap(const std::vector<uint8_t>& font_data);
296 void ApplyFontPalette();
298 void ImportMessageBundleFromFile(const std::string& path);
300
304 std::vector<std::string> current_parse_errors_;
305 std::vector<std::string> current_parse_warnings_;
306};
307
308} // namespace editor
309} // namespace yaze
310
311#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:49
Interface for editor classes.
Definition editor.h:249
UndoManager undo_manager_
Definition editor.h:371
zelda3::GameData * game_data() const
Definition editor.h:357
EditorDependencies dependencies_
Definition editor.h:370
EditorType type_
Definition editor.h:369
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)
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