yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
user_settings.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_SYSTEM_USER_SETTINGS_H_
2#define YAZE_APP_EDITOR_SYSTEM_USER_SETTINGS_H_
3
4#include <optional>
5#include <string>
6#include <unordered_map>
7#include <unordered_set>
8#include <utility>
9#include <vector>
10
11#include "absl/status/status.h"
12
13namespace yaze {
14namespace editor {
15
20 public:
21 struct Preferences {
22 struct AiHost {
23 std::string id;
24 std::string label;
25 std::string base_url;
26 std::string api_type; // openai, ollama, gemini, lmstudio, grpc
27 bool supports_vision = false;
28 bool supports_tools = true;
29 bool supports_streaming = true;
30 bool allow_insecure = false;
31 std::string api_key; // Optional plaintext key (desktop/non-keychain)
32 std::string
33 credential_id; // Keychain reference (never store secrets here)
34 };
35
37 std::string name;
38 std::string model;
39 float temperature = 0.25f;
40 float top_p = 0.95f;
42 bool supports_vision = false;
43 bool supports_tools = true;
44 };
45
46 // General
47 float font_global_scale = 1.0f;
48 bool backup_rom = false;
49 bool save_new_auto = true;
50 bool autosave_enabled = true;
51 float autosave_interval = 300.0f;
53 std::string last_rom_path;
54 std::string last_project_path;
56 // Test mode: launch without the welcome screen or editor picker and start
57 // the local test server (gRPC builds), so an agent that can only
58 // double-click the app gets a quiet, scriptable start. Next launch.
59 bool test_mode = false;
62
63 // One-shot feature tips (FeatureHintManager). Dismissed ids persist so
64 // ZScream/HM migrant tips do not re-fire after the user has seen them.
66 std::unordered_set<std::string> dismissed_feature_hints;
67
68 // Welcome screen animation preferences. Match the defaults hard-coded in
69 // WelcomeScreen so first-run behavior is unchanged.
75
76 // Accessibility / interaction
77 bool reduced_motion = false;
78 int switch_motion_profile = 1; // 0=Snappy, 1=Standard, 2=Relaxed
79
80 // Theme (last applied theme persists across restart; empty = default)
81 std::string last_theme_name;
82
83 // UI language (locale code, e.g. "en"/"fr"; matches assets/i18n/<code>.json)
84 std::string language_locale = "en";
85
86 // Font (index into ImGui::GetIO().Fonts->Fonts, typically 0..4)
88
89 // Editor Behavior
90 bool backup_before_save = true;
91 // 0=None, 1=Overworld, 2=Dungeon, 3=Graphics, 4=Messages (append only)
93
94 // Performance
95 bool vsync = true;
96 int target_fps = 60;
97 int cache_size_mb = 512;
99
100 // AI Agent
102 0; // Legacy default provider (0=Ollama, 1=Gemini, 2=Mock)
103 std::string ai_model;
104 std::string ollama_url = "http://localhost:11434";
105 std::string gemini_api_key;
106 std::string openai_api_key;
107 std::string anthropic_api_key;
108 float ai_temperature = 0.7f;
109 int ai_max_tokens = 2048;
110 bool ai_proactive = true;
111 bool ai_auto_learn = true;
112 bool ai_multimodal = true;
113 std::vector<AiHost> ai_hosts;
114 std::string active_ai_host_id;
115 std::vector<AiModelProfile> ai_profiles;
116 std::string active_ai_profile;
118 std::vector<std::string> ai_model_paths;
119
120 // CLI Logging
121 int log_level = 1; // 0=Debug, 1=Info, 2=Warning, 3=Error, 4=Fatal
122 bool log_to_file = false;
123 std::string log_file_path;
124 bool log_ai_requests = true;
127 bool log_proposals = true;
128
129 // Filesystem (iOS + remote workflows)
130 std::vector<std::string> project_root_paths;
132 bool use_files_app = true;
133 bool use_icloud_sync = true;
134
135 // Shortcut Overrides
136 // Maps panel_id -> shortcut string (e.g., "dungeon.room_selector" -> "Ctrl+Shift+R")
137 std::unordered_map<std::string, std::string> panel_shortcuts;
138 // Maps global action id -> shortcut string (e.g., "Open", "Save")
139 std::unordered_map<std::string, std::string> global_shortcuts;
140 // Maps editor-scoped action id -> shortcut string (keyed by editor namespace)
141 std::unordered_map<std::string, std::string> editor_shortcuts;
142
143 // Sidebar State
144 bool sidebar_visible = true; // Controls Activity Bar visibility
146 false; // WindowSidebar; ActivityBar-only default
147 float sidebar_panel_width = 0.0f; // 0 = responsive default
150 std::string sidebar_active_category; // Last active category
151
152 // Sidebar customization (Phase 4): user-controlled category order,
153 // hidden set (filtered out of the rail), and pinned set (pinned-first).
154 std::vector<std::string> sidebar_order;
155 std::unordered_set<std::string> sidebar_hidden;
156 std::unordered_set<std::string> sidebar_pinned;
157 std::unordered_set<std::string> sidebar_context_collapsed;
158
159 // Status Bar
161 false; // Show status bar at bottom (disabled by default)
162
163 // Emulator: keep ticking/audio when emulator panels are hidden.
164 // Default off — switching editors pauses the SNES.
166
167 // Legacy persisted name. This acknowledges experimental warnings and lets
168 // supported writers use their normal posture; it never hides an editor or
169 // bypasses a feature-specific write guard.
171
172 // Dungeon workbench layout: which side of the workbench window the
173 // inspector pane occupies. "left" (default) places object/entrance tools
174 // above the room matrix on the right; "right" mirrors that arrangement.
175 // Read by dungeon_workbench_content at draw time. Persisted as a string so
176 // a future "top" / "bottom" / "floating" extension does not require a
177 // migration of existing settings files.
178 std::string dungeon_inspector_side = "left";
179
180 // Panel Visibility State (per editor type)
181 // Maps editor_type_name -> (panel_id -> visible)
182 // e.g., "Overworld" -> {"overworld.tile16_selector" -> true, ...}
183 std::unordered_map<std::string, std::unordered_map<std::string, bool>>
185
186 // Pinned panels (persists across sessions)
187 // Maps panel_id -> pinned
188 std::unordered_map<std::string, bool> pinned_panels;
189 std::unordered_map<std::string, float> right_panel_widths;
190
191 // Named layouts (user-saved workspace configurations)
192 // Maps layout_name -> (panel_id -> visible)
193 std::unordered_map<std::string, std::unordered_map<std::string, bool>>
195
196 // Named DockTree layouts authored in the Layout Designer.
197 // Maps layout_name -> JSON-serialized DockTree (schema v1).
198 // Kept as opaque strings so UserSettings does not have to understand
199 // DockTree internals; the designer parses/re-serializes via
200 // layout_designer::DockTreeFromJson / DockTreeToJson.
201 std::unordered_map<std::string, std::string> named_layouts;
202
203 // Name of the last DockTree layout applied to the live dockspace.
204 // Empty string => nothing to auto-apply on startup. Mirrors the
205 // `last_theme_name` persistence pattern.
207
208 // Remembered ROM load options. Maps a RomLoadOptionsDialog::RomChoiceKey
209 // path -> that dialog's opaque encoding. A key that decodes and matches
210 // the ROM's ZSCustomOverworld byte skips the load options dialog.
211 std::unordered_map<std::string, std::string> rom_load_choices;
212 };
213
214 UserSettings();
215
216 absl::Status Load();
217 absl::Status Save();
218
219 // Applies one-time layout-default migrations when target_revision is newer
220 // than persisted settings. Returns true when preferences changed; callers
221 // must not assume every revision requires rebuilding the whole workspace.
222 bool ApplyPanelLayoutDefaultsRevision(int target_revision);
223
224 static constexpr int kLatestPanelLayoutDefaultsRevision = 30;
225 // Revisions through 21, and 27, changed whole-workspace arrangements.
226 // Revision 27 rebuilds once so the overworld map keeps its height: Tile16
227 // and area graphics share the right column, and nothing starts on the bottom.
228 // Revisions 22-26 and 28-30 are targeted preference migrations.
230
231 Preferences& prefs() { return prefs_; }
232 const Preferences& prefs() const { return prefs_; }
233
234 // Project workspace values for font scale, autosave, and backup-on-save.
235 // While an overlay is active these values are live in prefs(), but Save()
236 // keeps writing the user's own values, so opening a project never rewrites
237 // the global defaults. Edits made during an overlay belong to the project;
238 // ClearWorkspaceOverrides() restores the user's values.
240 float font_global_scale = 1.0f;
241 bool autosave_enabled = true;
242 float autosave_interval = 300.0f;
244 };
245 void ApplyWorkspaceOverrides(const WorkspaceOverrides& overrides);
247 bool HasWorkspaceOverrides() const { return workspace_baseline_.has_value(); }
248
249 // Dungeon workbench inspector placement. Returns the persisted value
250 // verbatim ("right" / "left"), defaulting to "right" if the value is empty
251 // or unrecognized so callers can switch on it without a null check.
252 std::string GetDungeonInspectorSide() const;
253 // Sets the inspector placement. Accepts "right" or "left"; any other value
254 // is normalized to "right". Caller must invoke Save() to persist.
255 void SetDungeonInspectorSide(std::string side);
256
257 // Testing hook: redirect JSON plus legacy INI Load/Save to caller-owned
258 // paths. Production code should never call this; it only exists so unit
259 // tests can exercise settings migration without touching the user's files.
260 void SetSettingsFilePathForTesting(std::string path) {
261 settings_file_path_ = std::move(path);
263 }
264 const std::string& settings_file_path() const { return settings_file_path_; }
265 const std::string& legacy_settings_file_path() const {
267 }
268
269 private:
271 // The user's own values for the WorkspaceOverrides fields while a project
272 // overlay is active; empty when prefs() holds only the user's values.
273 std::optional<WorkspaceOverrides> workspace_baseline_;
276};
277
278} // namespace editor
279} // namespace yaze
280
281#endif // YAZE_APP_EDITOR_SYSTEM_USER_SETTINGS_H_
Manages user preferences and settings persistence.
const Preferences & prefs() const
bool ApplyPanelLayoutDefaultsRevision(int target_revision)
const std::string & settings_file_path() const
const std::string & legacy_settings_file_path() const
void SetSettingsFilePathForTesting(std::string path)
std::string GetDungeonInspectorSide() const
void SetDungeonInspectorSide(std::string side)
static constexpr int kLatestPanelLayoutDefaultsRevision
void ApplyWorkspaceOverrides(const WorkspaceOverrides &overrides)
std::string legacy_settings_file_path_
std::optional< WorkspaceOverrides > workspace_baseline_
static constexpr int kLastWorkspaceResetPanelLayoutDefaultsRevision
std::unordered_set< std::string > sidebar_context_collapsed
std::vector< std::string > project_root_paths
std::unordered_map< std::string, std::string > panel_shortcuts
std::unordered_map< std::string, std::string > rom_load_choices
std::unordered_map< std::string, std::string > named_layouts
std::unordered_map< std::string, std::unordered_map< std::string, bool > > saved_layouts
std::vector< AiModelProfile > ai_profiles
std::unordered_set< std::string > sidebar_pinned
std::vector< std::string > sidebar_order
std::unordered_map< std::string, float > right_panel_widths
std::unordered_map< std::string, std::string > editor_shortcuts
std::vector< std::string > ai_model_paths
std::unordered_map< std::string, std::string > global_shortcuts
std::unordered_set< std::string > dismissed_feature_hints
std::unordered_map< std::string, std::unordered_map< std::string, bool > > panel_visibility_state
std::unordered_map< std::string, bool > pinned_panels
std::unordered_set< std::string > sidebar_hidden