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