19#include "imgui/imgui.h"
20#include "imgui/misc/cpp/imgui_stdlib.h"
30 ImGui::TextDisabled(
"Settings not available");
37 ImGuiTreeNodeFlags_DefaultOpen)) {
45 if (ImGui::CollapsingHeader(
ICON_MD_FOLDER " Project Configuration")) {
59 if (ImGui::CollapsingHeader(
ICON_MD_TUNE " Editor Behavior")) {
98 ImGui::TextDisabled(
"Feature Flags configuration");
106 if (ImGui::TreeNode(
ICON_MD_MAP " Overworld Flags")) {
129 ImGui::TextDisabled(
"No active project.");
145 if (ImGui::InputText(
"Output Folder", &output_folder)) {
152 if (ImGui::InputText(
"Git Repository", &git_repo)) {
163 if (ImGui::InputText(
"Build Target (ROM)", &build_target)) {
170 if (ImGui::InputText(
"Symbols File", &symbols_file)) {
183 ImGui::Text(
"Current Theme:");
185 auto current = theme_manager.GetCurrentThemeName();
186 ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
"%s", current.c_str());
191 ImGui::Text(
"Available Themes:");
193 if (ImGui::BeginChild(
"ThemeList", ImVec2(0, 150),
true)) {
194 for (
const auto& theme_name : theme_manager.GetAvailableThemes()) {
195 ImGui::PushID(theme_name.c_str());
196 bool is_current = (theme_name == current);
198 if (ImGui::Selectable(theme_name.c_str(), is_current)) {
199 theme_manager.LoadTheme(theme_name);
215 if (ImGui::Checkbox(
"Show Status Bar", &show_status_bar)) {
223 if (ImGui::IsItemHovered()) {
224 ImGui::SetTooltip(
"Display ROM, session, cursor, and zoom info at bottom of window");
234 if (ImGui::Checkbox(
"Enable Auto-Save",
242 if (ImGui::SliderInt(
"Interval (sec)", &interval, 60, 600)) {
247 if (ImGui::Checkbox(
"Backup Before Save",
258 if (ImGui::SliderInt(
"Limit",
267 const char* editors[] = {
"None",
"Overworld",
"Dungeon",
"Graphics"};
269 editors, IM_ARRAYSIZE(editors))) {
312 ImGui::Text(
"Current FPS: %.1f", ImGui::GetIO().Framerate);
313 ImGui::Text(
"Frame Time: %.3f ms", 1000.0f / ImGui::GetIO().Framerate);
323 const char* providers[] = {
"Ollama (Local)",
"Gemini (Cloud)",
"Mock (Testing)"};
325 IM_ARRAYSIZE(providers))) {
332 char url_buffer[256];
334 sizeof(url_buffer) - 1);
335 url_buffer[
sizeof(url_buffer) - 1] =
'\0';
336 if (ImGui::InputText(
"URL", url_buffer, IM_ARRAYSIZE(url_buffer))) {
341 char key_buffer[128];
343 sizeof(key_buffer) - 1);
344 key_buffer[
sizeof(key_buffer) - 1] =
'\0';
345 if (ImGui::InputText(
"API Key", key_buffer, IM_ARRAYSIZE(key_buffer),
346 ImGuiInputTextFlags_Password)) {
360 ImGui::TextDisabled(
"Higher = more creative");
371 if (ImGui::Checkbox(
"Proactive Suggestions",
376 if (ImGui::Checkbox(
"Auto-Learn Preferences",
381 if (ImGui::Checkbox(
"Enable Vision",
390 const char* log_levels[] = {
"Debug",
"Info",
"Warning",
"Error",
"Fatal"};
392 IM_ARRAYSIZE(log_levels))) {
399 if (ImGui::TreeNodeEx(
ICON_MD_KEYBOARD " Shortcuts", ImGuiTreeNodeFlags_DefaultOpen)) {
400 if (ImGui::TreeNode(
"Global Shortcuts")) {
404 if (ImGui::TreeNode(
"Editor Shortcuts")) {
408 if (ImGui::TreeNode(
"Panel Shortcuts")) {
412 ImGui::TextDisabled(
"Tip: Use Cmd/Opt labels on macOS or Ctrl/Alt on Windows/Linux. Function keys and symbols (/, -) are supported.");
419 ImGui::TextDisabled(
"Not available");
424 if (shortcuts.empty()) {
425 ImGui::TextDisabled(
"No global shortcuts registered.");
429 static std::unordered_map<std::string, std::string> editing;
431 for (
const auto& sc : shortcuts) {
432 auto it = editing.find(sc.name);
433 if (it == editing.end()) {
440 editing[sc.name] = current;
443 ImGui::PushID(sc.name.c_str());
444 ImGui::Text(
"%s", sc.name.c_str());
446 ImGui::SetNextItemWidth(180);
447 std::string& value = editing[sc.name];
448 if (ImGui::InputText(
"##global", &value,
449 ImGuiInputTextFlags_EnterReturnsTrue |
450 ImGuiInputTextFlags_AutoSelectAll)) {
452 if (!parsed.empty() || value.empty()) {
469 ImGui::TextDisabled(
"Not available");
474 std::map<std::string, std::vector<Shortcut>> grouped;
475 static std::unordered_map<std::string, std::string> editing;
477 for (
const auto& sc : shortcuts) {
478 auto pos = sc.name.find(
".");
479 std::string group = pos != std::string::npos ? sc.name.substr(0, pos) :
"general";
480 grouped[group].push_back(sc);
482 for (
const auto& [group, list] : grouped) {
483 if (ImGui::TreeNode(group.c_str())) {
484 for (
const auto& sc : list) {
485 ImGui::PushID(sc.name.c_str());
486 ImGui::Text(
"%s", sc.name.c_str());
488 ImGui::SetNextItemWidth(180);
489 std::string& value = editing[sc.name];
498 if (ImGui::InputText(
"##editor", &value, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
500 if (!parsed.empty() || value.empty()) {
519 ImGui::TextDisabled(
"Registry not available");
526 for (
const auto& category : categories) {
527 if (ImGui::TreeNode(category.c_str())) {
530 for (
const auto& card : cards) {
531 ImGui::PushID(card.card_id.c_str());
533 ImGui::Text(
"%s %s", card.icon.c_str(), card.display_name.c_str());
535 std::string current_shortcut;
538 current_shortcut = it->second;
539 }
else if (!card.shortcut_hint.empty()) {
540 current_shortcut = card.shortcut_hint;
542 current_shortcut =
"None";
546 std::string display_shortcut = current_shortcut;
548 if (!parsed.empty()) {
553 ImGui::SetNextItemWidth(120);
554 ImGui::SetKeyboardFocusHere();
557 ImGuiInputTextFlags_EnterReturnsTrue)) {
573 if (ImGui::Button(display_shortcut.c_str(), ImVec2(120, 0))) {
578 if (ImGui::IsItemHovered()) {
579 ImGui::SetTooltip(
"Click to edit shortcut");
596 if (patches_dir_status.ok()) {
611 ImGui::TextDisabled(
"No patches loaded");
612 ImGui::TextDisabled(
"Place .asm patches in assets/patches/");
614 if (ImGui::Button(
"Browse for Patches Folder...")) {
623 ImGui::Text(
"Loaded: %d patches (%d enabled)", total_count, enabled_count);
628 if (ImGui::BeginTabBar(
"##PatchFolders", ImGuiTabBarFlags_FittingPolicyScroll)) {
630 if (ImGui::BeginTabItem(folder.c_str())) {
646 ImGui::TextDisabled(
"Select a patch to view details");
657 LOG_ERROR(
"Settings",
"Failed to apply patches: %s", status.message());
659 LOG_INFO(
"Settings",
"Applied %d patches successfully", enabled_count);
662 LOG_WARN(
"Settings",
"No ROM loaded");
665 if (ImGui::IsItemHovered()) {
666 ImGui::SetTooltip(
"Apply all enabled patches to the loaded ROM");
673 LOG_ERROR(
"Settings",
"Failed to save patches: %s", status.message());
686 if (patches.empty()) {
687 ImGui::TextDisabled(
"No patches in this folder");
692 float available_height = std::min(200.0f, patches.size() * 25.0f + 10.0f);
693 if (ImGui::BeginChild(
"##PatchList", ImVec2(0, available_height),
true)) {
694 for (
auto* patch : patches) {
695 ImGui::PushID(patch->filename().c_str());
697 bool enabled = patch->enabled();
698 if (ImGui::Checkbox(
"##Enabled", &enabled)) {
699 patch->set_enabled(enabled);
706 if (ImGui::Selectable(patch->name().c_str(), is_selected)) {
738 if (!params.empty()) {
743 for (
auto& param : params) {
754 switch (param->
type) {
758 int value = param->
value;
759 const char* format = param->
use_decimal ?
"%d" :
"$%X";
762 ImGui::SetNextItemWidth(100);
763 if (ImGui::InputInt(
"##Value", &value, 1, 16)) {
777 if (ImGui::Checkbox(param->
display_name.c_str(), &checked)) {
785 for (
size_t i = 0; i < param->
choices.size(); ++i) {
786 bool selected = (param->
value ==
static_cast<int>(i));
787 if (ImGui::RadioButton(param->
choices[i].c_str(), selected)) {
788 param->
value =
static_cast<int>(i);
796 for (
size_t i = 0; i < param->
choices.size(); ++i) {
800 bool bit_set = (param->
value & (1 << i)) != 0;
801 if (ImGui::Checkbox(param->
choices[i].c_str(), &bit_set)) {
803 param->
value |= (1 << i);
805 param->
value &= ~(1 << i);
815 ImGui::SetNextItemWidth(150);
816 if (ImGui::InputInt(
"Item ID", ¶m->
value)) {
817 param->
value = std::clamp(param->
value, 0, 255);
const std::string & version() const
std::vector< PatchParameter > & mutable_parameters()
const std::string & author() const
const std::string & description() const
const std::string & name() const
absl::Status ApplyEnabledPatches(Rom *rom)
Apply all enabled patches to a ROM.
absl::Status SaveAllPatches()
Save all patches to their files.
const std::vector< std::string > & folders() const
Get list of patch folder names.
int GetEnabledPatchCount() const
Get count of enabled patches.
std::vector< AsmPatch * > GetPatchesInFolder(const std::string &folder)
Get all patches in a specific folder.
const std::vector< std::unique_ptr< AsmPatch > > & patches() const
Get all loaded patches.
absl::Status LoadPatches(const std::string &patches_dir)
Load all patches from a directory structure.
std::vector< std::string > GetAllCategories(size_t session_id) const
std::vector< PanelDescriptor > GetPanelsInCategory(size_t session_id, const std::string &category) const
void DrawPerformanceSettings()
std::string editing_card_id_
void DrawProjectSettings()
void DrawPatchList(const std::string &folder)
void DrawAppearanceSettings()
PanelManager * panel_manager_
char shortcut_edit_buffer_[64]
ShortcutManager * shortcut_manager_
void DrawEditorShortcuts()
void DrawGlobalShortcuts()
void DrawParameterWidget(core::PatchParameter *param)
void DrawEditorBehavior()
core::AsmPatch * selected_patch_
void DrawGeneralSettings()
core::PatchManager patch_manager_
project::YazeProject * project_
std::string selected_folder_
UserSettings * user_settings_
void DrawKeyboardShortcuts()
bool is_editing_shortcut_
void DrawPanelShortcuts()
void DrawAIAgentSettings()
std::vector< Shortcut > GetShortcutsByScope(Shortcut::Scope scope) const
bool UpdateShortcutKeys(const std::string &name, const std::vector< ImGuiKey > &keys)
void SetEnabled(bool enabled)
Enable or disable the status bar.
static ThemeManager & Get()
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_FOLDER_SPECIAL
#define ICON_MD_EXTENSION
#define ICON_MD_PSYCHOLOGY
#define ICON_MD_HORIZONTAL_RULE
#define ICON_MD_SMART_TOY
#define LOG_ERROR(category, format,...)
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
std::vector< ImGuiKey > ParseShortcut(const std::string &shortcut)
std::string PrintShortcut(const std::vector< ImGuiKey > &keys)
void SetPreferHmagicSpriteNames(bool prefer)
Represents a configurable parameter within an ASM patch.
std::vector< std::string > choices
std::string gemini_api_key
std::unordered_map< std::string, std::string > panel_shortcuts
std::unordered_map< std::string, std::string > editor_shortcuts
std::unordered_map< std::string, std::string > global_shortcuts
bool prefer_hmagic_sprite_names
std::string git_repository
std::string output_folder
std::string symbols_filename