imgui-frontend-engineer: move layout designer into lab target

This commit is contained in:
scawful
2025-12-28 09:56:41 -06:00
parent d002f5556d
commit b78e167105
27 changed files with 557 additions and 114 deletions

View File

@@ -9,6 +9,7 @@ option(YAZE_BUILD_EMU "Build emulator components" ON)
option(YAZE_BUILD_LIB "Build static library" ON)
option(YAZE_BUILD_TESTS "Build test suite" ON)
option(YAZE_BUILD_TOOLS "Build development utility tools" ${YAZE_BUILD_TESTS})
option(YAZE_BUILD_LAB "Build lab sandbox executable" OFF)
# Feature flags
option(YAZE_ENABLE_GRPC "Enable gRPC agent support" ON)
@@ -132,6 +133,7 @@ message(STATUS "z3ed CLI: ${YAZE_BUILD_Z3ED}")
message(STATUS "Emulator: ${YAZE_BUILD_EMU}")
message(STATUS "Static Library: ${YAZE_BUILD_LIB}")
message(STATUS "Tests: ${YAZE_BUILD_TESTS}")
message(STATUS "Lab Sandbox: ${YAZE_BUILD_LAB}")
if(YAZE_USE_SDL3)
message(STATUS "SDL Version: SDL3 (experimental)")
else()

View File

@@ -1,32 +1,31 @@
# Layout Designer (December 2025)
Canonical reference for the ImGui layout designer utility that lives in `src/app/editor/layout_designer/`. Use this in place of the older phase-by-phase notes and mockups.
Canonical reference for the ImGui layout designer utility that lives in `src/lab/layout_designer/`. Use this in place of the older phase-by-phase notes and mockups.
## Current Capabilities
- **Two modes**: Panel Layout (dock graph editing) and Widget Design (panel internals) toggled in the toolbar of `LayoutDesignerWindow`.
- **Panel layout mode**: Palette from `PanelManager` descriptors with search/category filter, drag-and-drop into a dock tree with split drop-zones, selection + property editing, zoom controls, optional code preview, and a theme panel. JSON export writes via `LayoutSerializer::SaveToFile`; import/export dialogs are stubbed.
- **Widget design mode**: Palette from `yaze_widgets`, canvas + properties UI, and code generation through `WidgetCodeGenerator` (deletion/undo/redo are still TODOs).
- **Runtime import**: `ImportFromRuntime()` builds a flat layout from the registered `PanelDescriptor`s (no live dock positions yet). `PreviewLayout()` is stubbed and does not apply to the running dockspace.
- **Runtime import**: `ImportFromRuntime()` builds a flat layout from the registered `PanelDescriptor`s (no live dock positions yet). `PreviewLayout()` can apply DockBuilder ops against `MainDockSpace` when `LayoutManager` + `PanelManager` are wired, but it does not persist layouts.
## Integration Quick Start
- **Lab target**: Build with `-DYAZE_BUILD_LAB=ON` and run the `lab` executable. The lab host opens the designer by default and provides the `MainDockSpace` dockspace for preview/testing.
- **Embedding**: If you want to host the designer elsewhere, wire it with a `PanelManager` + `LayoutManager` and draw it each frame.
```cpp
// EditorManager member
layout_designer::LayoutDesignerWindow layout_designer_;
#include "lab/layout_designer/layout_designer_window.h"
// Init once with the panel manager
layout_designer_.Initialize(&panel_manager_);
layout_designer::LayoutDesignerWindow layout_designer;
layout_designer.Initialize(&panel_manager, &layout_manager, nullptr);
layout_designer.Open();
// Open from menu or shortcut
layout_designer_.Open();
// Draw every frame
if (layout_designer_.IsOpen()) {
layout_designer_.Draw();
if (layout_designer.IsOpen()) {
layout_designer.Draw();
}
```
## Improvement Backlog (code-aligned)
1. **Preview/apply pipeline**: Implement `LayoutDesignerWindow::PreviewLayout()` to transform a `LayoutDefinition` into DockBuilder operations (use `PanelDescriptor::GetWindowTitle()` and the active dockspace ID from `LayoutManager`). Ensure session-aware panel IDs and call back into `LayoutManager`/`PanelManager` so visibility state stays in sync.
1. **Preview/apply pipeline**: Extend `LayoutDesignerWindow::PreviewLayout()` to cover full `LayoutManager` integration (persisted layouts + session-aware visibility) and avoid relying solely on `MainDockSpace`.
2. **Serialization round-trip**: Finish `LayoutSerializer::FromJson()` and wire real open/save dialogs. Validate versions/author fields and surface parse errors in the UI. Add a simple JSON schema example to `layout_designer/README.md` once load works.
3. **Runtime import fidelity**: Replace the flat import in `ImportFromRuntime()` with actual dock sampling (dock nodes, split ratios, and current visible panels), filtering out dashboard/welcome. Capture panel visibility per session instead of assuming all-visible defaults.
4. **Editing polish**: Implement delete/undo/redo for panels/widgets, and make widget deletion/selection consistent across both modes. Reduce debug logging spam (`DragDrop` noise) once the drop pipeline is stable.

View File

@@ -110,7 +110,7 @@ endif()
# Include agent/CLI components (needed by yaze_editor for agent features)
# NOTE: yaze_agent depends on yaze_app_core_lib, so we must include app.cmake
# BEFORE cli/agent.cmake when building agent features
if(YAZE_BUILD_GUI OR YAZE_BUILD_Z3ED OR YAZE_BUILD_TESTS)
if(YAZE_BUILD_GUI OR YAZE_BUILD_Z3ED OR YAZE_BUILD_TESTS OR YAZE_BUILD_LAB OR YAZE_PLATFORM_IOS)
include(app/app.cmake)
endif()
@@ -127,6 +127,11 @@ if(YAZE_BUILD_EMU)
include(app/emu/emu.cmake)
endif()
# Build lab sandbox target
if(YAZE_BUILD_LAB)
include(lab/lab.cmake)
endif()
# Build z3ed CLI tool
if(YAZE_BUILD_Z3ED)
include(cli/z3ed.cmake)

View File

@@ -70,25 +70,6 @@ set(
app/editor/palette/palette_utility.cc
app/editor/sprite/sprite_drawer.cc
app/editor/sprite/sprite_editor.cc
app/editor/layout/layout_coordinator.cc
app/editor/layout/layout_manager.cc
app/editor/layout/layout_orchestrator.cc
app/editor/layout/layout_presets.cc
app/editor/layout/window_delegate.cc
app/editor/system/command_manager.cc
app/editor/system/command_palette.cc
app/editor/system/editor_activator.cc
app/editor/system/panel_manager.cc
app/editor/system/file_browser.cc
app/editor/system/editor_registry.cc
app/editor/system/extension_manager.cc
app/editor/system/project_manager.cc
app/editor/system/proposal_drawer.cc
app/editor/system/rom_file_manager.cc
app/editor/system/shortcut_manager.cc
app/editor/system/session_coordinator.cc
app/editor/system/user_settings.cc
app/editor/system/shortcut_configurator.cc
app/editor/menu/menu_orchestrator.cc
app/editor/ui/popup_manager.cc
app/editor/ui/dashboard_panel.cc
@@ -105,16 +86,91 @@ set(
app/editor/ui/welcome_screen.cc
app/editor/ui/workspace_manager.cc
app/editor/layout_designer/layout_designer_window.cc
app/editor/layout_designer/layout_serialization.cc
app/editor/layout_designer/layout_definition.cc
app/editor/layout_designer/widget_definition.cc
app/editor/layout_designer/widget_code_generator.cc
app/editor/layout_designer/theme_properties.cc
app/editor/layout_designer/yaze_widgets.cc
yaze.cc
)
set(
YAZE_EDITOR_SYSTEM_PANELS_SRC
app/editor/layout/layout_coordinator.cc
app/editor/layout/layout_manager.cc
app/editor/layout/layout_orchestrator.cc
app/editor/layout/layout_presets.cc
app/editor/layout/window_delegate.cc
app/editor/system/editor_activator.cc
app/editor/system/editor_registry.cc
app/editor/system/panel_manager.cc
app/editor/system/file_browser.cc
app/editor/system/proposal_drawer.cc
)
set(
YAZE_EDITOR_SYSTEM_SESSION_SRC
app/editor/system/extension_manager.cc
app/editor/system/project_manager.cc
app/editor/system/rom_file_manager.cc
app/editor/system/session_coordinator.cc
app/editor/system/user_settings.cc
)
set(
YAZE_EDITOR_SYSTEM_SHORTCUTS_SRC
app/editor/system/command_manager.cc
app/editor/system/command_palette.cc
app/editor/system/shortcut_manager.cc
app/editor/system/shortcut_configurator.cc
)
# Editor system split targets (panels/session/shortcuts)
add_library(yaze_editor_system_panels STATIC ${YAZE_EDITOR_SYSTEM_PANELS_SRC})
add_library(yaze_editor_system_session STATIC ${YAZE_EDITOR_SYSTEM_SESSION_SRC})
add_library(yaze_editor_system_shortcuts STATIC ${YAZE_EDITOR_SYSTEM_SHORTCUTS_SRC})
foreach(target_name IN ITEMS
yaze_editor_system_panels
yaze_editor_system_session
yaze_editor_system_shortcuts
)
target_precompile_headers(${target_name} PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/src/yaze_pch.h>"
)
target_include_directories(${target_name} PUBLIC
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/ext
${CMAKE_SOURCE_DIR}/ext/imgui
${CMAKE_SOURCE_DIR}/ext/imgui_test_engine
${CMAKE_SOURCE_DIR}/incl
${SDL2_INCLUDE_DIR}
${PROJECT_BINARY_DIR}
)
endforeach()
target_link_libraries(yaze_editor_system_panels PUBLIC
yaze_app_core_lib
yaze_gfx
yaze_gui
yaze_util
yaze_common
ImGui
)
target_link_libraries(yaze_editor_system_session PUBLIC
yaze_editor_system_panels
yaze_rom
yaze_zelda3
yaze_gui
yaze_util
yaze_common
ImGui
)
target_link_libraries(yaze_editor_system_shortcuts PUBLIC
yaze_gui
yaze_util
yaze_common
ImGui
)
# Agent UI Theme is always needed (used by dungeon editor, etc.)
list(APPEND YAZE_APP_EDITOR_SRC
app/editor/agent/agent_ui_theme.cc
@@ -155,6 +211,21 @@ endif()
add_library(yaze_editor STATIC ${YAZE_APP_EDITOR_SRC})
target_link_libraries(yaze_editor PUBLIC
yaze_editor_system_panels
yaze_editor_system_session
yaze_editor_system_shortcuts
yaze_app_core_lib
yaze_rom
yaze_gfx
yaze_gui
yaze_zelda3
yaze_emulator # Needed for emulator integration (APU, PPU, SNES)
yaze_util
yaze_common
ImGui
)
target_precompile_headers(yaze_editor PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/src/yaze_pch.h>"
)
@@ -169,18 +240,6 @@ target_include_directories(yaze_editor PUBLIC
${PROJECT_BINARY_DIR}
)
target_link_libraries(yaze_editor PUBLIC
yaze_app_core_lib
yaze_rom
yaze_gfx
yaze_gui
yaze_zelda3
yaze_emulator # Needed for emulator integration (APU, PPU, SNES)
yaze_util
yaze_common
ImGui
)
# Link agent runtime only when agent UI panels are enabled
if(YAZE_BUILD_AGENT_UI AND NOT YAZE_MINIMAL_BUILD)
if(TARGET yaze_agent)
@@ -195,6 +254,7 @@ endif()
if(YAZE_ENABLE_JSON)
if(TARGET nlohmann_json::nlohmann_json)
target_link_libraries(yaze_editor_system_panels PUBLIC nlohmann_json::nlohmann_json)
target_link_libraries(yaze_editor PUBLIC nlohmann_json::nlohmann_json)
endif()

View File

@@ -481,9 +481,6 @@ void EditorManager::Initialize(gfx::IRenderer* renderer,
emulator_.set_panel_manager(&panel_manager_);
workspace_manager_.set_panel_manager(&panel_manager_);
// Initialize layout designer with panel + layout managers
layout_designer_.Initialize(&panel_manager_, layout_manager_.get(), this);
// Point to a blank editor set when no ROM is loaded
// current_editor_set_ = &blank_editor_set_;
@@ -1273,11 +1270,6 @@ absl::Status EditorManager::Update() {
session_coordinator_->DrawSessionRenameDialog();
}
// Draw Layout Designer if open
if (layout_designer_.IsOpen()) {
layout_designer_.Draw();
}
return absl::OkStatus();
}

View File

@@ -41,7 +41,6 @@
#include "app/editor/ui/ui_coordinator.h"
#include "app/editor/ui/welcome_screen.h"
#include "app/editor/ui/workspace_manager.h"
#include "app/editor/layout_designer/layout_designer_window.h"
#include "app/emu/emulator.h"
#include "app/startup_flags.h"
#include "rom/rom.h"
@@ -114,7 +113,6 @@ class EditorManager : public SessionObserver {
auto quit() const { return quit_; }
auto version() const { return version_; }
void OpenLayoutDesigner() { layout_designer_.Open(); }
MenuBuilder& menu_builder() { return menu_builder_; }
WorkspaceManager* workspace_manager() { return &workspace_manager_; }
@@ -427,7 +425,6 @@ class EditorManager : public SessionObserver {
StatusBar status_bar_; // Bottom status bar
std::unique_ptr<ActivityBar> activity_bar_;
WorkspaceManager workspace_manager_{&toast_manager_};
layout_designer::LayoutDesignerWindow layout_designer_; // WYSIWYG layout designer
emu::input::InputConfig BuildInputConfigFromSettings() const;
void PersistInputConfig(const emu::input::InputConfig& config);

View File

@@ -286,8 +286,6 @@ void MenuOrchestrator::AddToolsMenuItems() {
[this]() { OnShowCommandPalette(); }, SHORTCUT_CTRL_SHIFT(P))
.Item("Resource Label Manager", ICON_MD_LABEL,
[this]() { OnShowResourceLabelManager(); })
.Item("Layout Designer", ICON_MD_DASHBOARD,
[this]() { OnShowLayoutDesigner(); }, SHORTCUT_CTRL(L))
.Separator();
// ROM Analysis (moved from Debug menu)
@@ -750,13 +748,6 @@ void MenuOrchestrator::OnShowWelcomeScreen() {
}
}
void MenuOrchestrator::OnShowLayoutDesigner() {
// Open the WYSIWYG layout designer
if (editor_manager_) {
editor_manager_->OpenLayoutDesigner();
}
}
#ifdef YAZE_BUILD_AGENT_UI
void MenuOrchestrator::OnShowAIAgent() {
if (editor_manager_) {

View File

@@ -98,7 +98,6 @@ class MenuOrchestrator {
void OnShowEmulator();
void OnShowPanelBrowser();
void OnShowWelcomeScreen();
void OnShowLayoutDesigner();
#ifdef YAZE_BUILD_AGENT_UI
void OnShowAIAgent();

46
src/lab/lab.cmake Normal file
View File

@@ -0,0 +1,46 @@
# ==============================================================================
# Lab sandbox executable
# ==============================================================================
set(YAZE_LAB_SRC
lab/main.cc
lab/layout_designer/layout_designer_window.cc
lab/layout_designer/layout_serialization.cc
lab/layout_designer/layout_definition.cc
lab/layout_designer/widget_definition.cc
lab/layout_designer/widget_code_generator.cc
lab/layout_designer/theme_properties.cc
lab/layout_designer/yaze_widgets.cc
)
add_executable(yaze_lab ${YAZE_LAB_SRC})
set_target_properties(yaze_lab PROPERTIES OUTPUT_NAME "lab")
target_precompile_headers(yaze_lab PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/src/yaze_pch.h>"
)
target_include_directories(yaze_lab PUBLIC
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/ext
${CMAKE_SOURCE_DIR}/ext/imgui
${CMAKE_SOURCE_DIR}/incl
${SDL2_INCLUDE_DIR}
${PROJECT_BINARY_DIR}
)
target_link_libraries(yaze_lab PRIVATE
yaze_editor_system_panels
yaze_app_core_lib
yaze_gui
yaze_gfx
yaze_util
yaze_common
ImGui
)
if(APPLE)
target_link_libraries(yaze_lab PUBLIC "-framework Cocoa")
endif()
message(STATUS "✓ yaze_lab sandbox target configured")

View File

@@ -2,7 +2,8 @@
## Opening the Designer
**Press `Ctrl+L`** or go to **`Tools > Layout Designer`**
Build with `-DYAZE_BUILD_LAB=ON`, then run the `lab` executable. The designer
opens by default in the lab host.
---
@@ -247,7 +248,6 @@ TabBar: "tabs"
| Shortcut | Action |
|----------|--------|
| `Ctrl+L` | Open Layout Designer |
| `Ctrl+N` | New layout/design |
| `Ctrl+O` | Open file |
| `Ctrl+S` | Save file |
@@ -260,10 +260,10 @@ TabBar: "tabs"
## Troubleshooting
### Q: Designer doesn't open
**A:** Check that yaze is running and press `Ctrl+L` or use `Tools > Layout Designer`
**A:** Make sure you're running the `lab` executable (built with `YAZE_BUILD_LAB`).
### Q: Palette is empty (Panel mode)
**A:** Load a ROM first. Some panels only appear when ROM is loaded.
**A:** In the lab host, confirm `RegisterLabPanels()` is seeding descriptors. If embedding in the main editor, load a ROM so session panels register.
### Q: Palette is empty (Widget mode)
**A:** This is a bug. Widget palette should always show all 40+ widget types.
@@ -338,4 +338,3 @@ TabBar: "tabs"
---
Happy designing! 🎨

View File

@@ -27,32 +27,29 @@ The Layout Designer provides a visual interface for designing complex multi-pane
## Quick Start
### Opening the Designer
### Opening the Designer (Lab)
1. Configure with `-DYAZE_BUILD_LAB=ON`
2. Build and run the `lab` executable
3. The layout designer opens on launch and targets `MainDockSpace` for preview
### Embedding in Another Host
```cpp
// In EditorManager or main menu
#include "app/editor/layout_designer/layout_designer_window.h"
#include "lab/layout_designer/layout_designer_window.h"
// Member variable
layout_designer::LayoutDesignerWindow layout_designer_;
layout_designer::LayoutDesignerWindow layout_designer;
layout_designer.Initialize(&panel_manager, &layout_manager, nullptr);
layout_designer.Open();
// Initialize
layout_designer_.Initialize(&panel_manager_);
// Open from menu
if (ImGui::MenuItem(ICON_MD_DASHBOARD " Layout Designer")) {
layout_designer_.Open();
}
// Draw each frame
if (layout_designer_.IsOpen()) {
layout_designer_.Draw();
if (layout_designer.IsOpen()) {
layout_designer.Draw();
}
```
### Creating a Layout
1. **Open Designer:** Tools > Layout Designer
1. **Open Designer:** Launch the lab target (or embed the window in a host)
2. **Create New Layout:** File > New (Ctrl+N)
3. **Add Panels:**
- Drag panels from palette on the left
@@ -306,4 +303,3 @@ cmake --build build
## License
Same as yaze project license.

View File

@@ -219,7 +219,7 @@ void DrawDropZones(...) {
Run through these steps to verify drag-drop works:
- [ ] Open Layout Designer (Ctrl+L)
- [ ] Launch the `lab` executable (built with `YAZE_BUILD_LAB`)
- [ ] Verify Panel Layout mode is selected
- [ ] See panels in left palette
- [ ] Click and HOLD on "Room List" panel
@@ -357,4 +357,3 @@ if (const ImGuiPayload* payload =
```
This avoids copying std::string in the payload!

View File

@@ -1,4 +1,4 @@
#include "app/editor/layout_designer/layout_definition.h"
#include "lab/layout_designer/layout_definition.h"
#include <chrono>

View File

@@ -1,5 +1,5 @@
#define IMGUI_DEFINE_MATH_OPERATORS
#include "app/editor/layout_designer/layout_designer_window.h"
#include "lab/layout_designer/layout_designer_window.h"
#include <algorithm>
#include <functional>
@@ -9,9 +9,9 @@
#include <unordered_set>
#include "absl/strings/str_format.h"
#include "app/editor/layout_designer/layout_serialization.h"
#include "app/editor/layout_designer/widget_code_generator.h"
#include "app/editor/layout_designer/yaze_widgets.h"
#include "lab/layout_designer/layout_serialization.h"
#include "lab/layout_designer/widget_code_generator.h"
#include "lab/layout_designer/yaze_widgets.h"
#include "app/gui/core/icons.h"
#include "imgui/imgui.h"
#include "imgui/imgui_internal.h"

View File

@@ -6,9 +6,9 @@
#include <vector>
#include <optional>
#include "app/editor/layout_designer/layout_definition.h"
#include "app/editor/layout_designer/widget_definition.h"
#include "app/editor/layout_designer/theme_properties.h"
#include "lab/layout_designer/layout_definition.h"
#include "lab/layout_designer/widget_definition.h"
#include "lab/layout_designer/theme_properties.h"
#include "app/editor/system/panel_manager.h"
#define IMGUI_DEFINE_MATH_OPERATORS

View File

@@ -1,4 +1,4 @@
#include "app/editor/layout_designer/layout_serialization.h"
#include "lab/layout_designer/layout_serialization.h"
#include <fstream>
#include <sstream>

View File

@@ -3,7 +3,7 @@
#include <string>
#include "app/editor/layout_designer/layout_definition.h"
#include "lab/layout_designer/layout_definition.h"
#include "absl/status/statusor.h"
namespace yaze {

View File

@@ -1,4 +1,4 @@
#include "app/editor/layout_designer/theme_properties.h"
#include "lab/layout_designer/theme_properties.h"
#include "absl/strings/str_format.h"
#include "app/gui/core/icons.h"

View File

@@ -1,4 +1,4 @@
#include "app/editor/layout_designer/widget_code_generator.h"
#include "lab/layout_designer/widget_code_generator.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_replace.h"

View File

@@ -4,7 +4,7 @@
#include <string>
#include <vector>
#include "app/editor/layout_designer/widget_definition.h"
#include "lab/layout_designer/widget_definition.h"
namespace yaze {
namespace editor {

View File

@@ -1,4 +1,4 @@
#include "app/editor/layout_designer/widget_definition.h"
#include "lab/layout_designer/widget_definition.h"
#include <chrono>

View File

@@ -1,4 +1,4 @@
#include "app/editor/layout_designer/yaze_widgets.h"
#include "lab/layout_designer/yaze_widgets.h"
#include "absl/strings/str_format.h"
#include "app/gui/core/icons.h"

View File

@@ -1,7 +1,7 @@
#ifndef YAZE_APP_EDITOR_LAYOUT_DESIGNER_YAZE_WIDGETS_H_
#define YAZE_APP_EDITOR_LAYOUT_DESIGNER_YAZE_WIDGETS_H_
#include "app/editor/layout_designer/widget_definition.h"
#include "lab/layout_designer/widget_definition.h"
namespace yaze {
namespace editor {

358
src/lab/main.cc Normal file
View File

@@ -0,0 +1,358 @@
#include <cstdlib>
#include <set>
#include <string>
#include "app/editor/layout/layout_manager.h"
#include "app/editor/system/panel_manager.h"
#include "app/gfx/backend/renderer_factory.h"
#include "app/platform/iwindow.h"
#include "app/platform/sdl_compat.h"
#include "app/gui/core/icons.h"
#include "lab/layout_designer/layout_designer_window.h"
#include "imgui/imgui.h"
#include "util/log.h"
namespace {
constexpr size_t kLabSessionId = 0;
struct LabPanelSeed {
const char* id;
const char* display_name;
const char* window_title;
const char* icon;
const char* category;
const char* shortcut;
const char* disabled_tooltip;
int priority;
bool visible_by_default;
};
constexpr LabPanelSeed kLabPanels[] = {
// Overworld
{"overworld.canvas", "Overworld Canvas", nullptr, ICON_MD_MAP, "Overworld",
"Ctrl+Shift+O", nullptr, 5, true},
{"overworld.area_graphics", "Area Graphics", nullptr, ICON_MD_IMAGE,
"Overworld", nullptr, nullptr, 50, false},
{"overworld.tile16_selector", "Tile16 Selector", nullptr, ICON_MD_GRID_ON,
"Overworld", nullptr, nullptr, 50, true},
{"overworld.tile16_editor", "Tile16 Editor", nullptr, ICON_MD_EDIT,
"Overworld", nullptr, nullptr, 15, false},
{"overworld.tile8_selector", "Tile8 Selector", nullptr, ICON_MD_GRID_3X3,
"Overworld", nullptr, nullptr, 50, false},
{"overworld.properties", "Map Properties", nullptr, ICON_MD_TUNE,
"Overworld", nullptr, nullptr, 50, false},
{"overworld.scratch", "Scratch Workspace", nullptr, ICON_MD_DRAW,
"Overworld", nullptr, nullptr, 50, false},
{"overworld.usage_stats", "Usage Statistics", nullptr, ICON_MD_ANALYTICS,
"Overworld", nullptr, nullptr, 50, false},
{"overworld.debug", "Debug Window", nullptr, ICON_MD_BUG_REPORT,
"Overworld", nullptr, nullptr, 50, false},
{"overworld.gfx_groups", "Graphics Groups", nullptr, ICON_MD_COLLECTIONS,
"Overworld", nullptr, nullptr, 50, false},
{"overworld.v3_settings", "v3 Settings", nullptr, ICON_MD_SETTINGS,
"Overworld", nullptr, nullptr, 50, false},
// Dungeon
{"dungeon.control_panel", "Dungeon Controls", " Dungeon Controls",
ICON_MD_CASTLE, "Dungeon", "Ctrl+Shift+D",
"Load a ROM to access dungeon controls", 10, false},
{"dungeon.room_selector", "Room List", " Room List", ICON_MD_LIST,
"Dungeon", "Ctrl+Shift+R", "Load a ROM to browse dungeon rooms", 20,
false},
{"dungeon.entrance_list", "Entrance List", " Entrance List",
ICON_MD_DOOR_FRONT, "Dungeon", "Ctrl+Shift+E",
"Load a ROM to browse dungeon entrances", 25, false},
{"dungeon.entrance_properties", "Entrance Properties",
" Entrance Properties", ICON_MD_TUNE, "Dungeon", nullptr,
"Load a ROM to edit entrance properties", 26, false},
{"dungeon.room_matrix", "Room Matrix", " Room Matrix", ICON_MD_GRID_VIEW,
"Dungeon", "Ctrl+Shift+M", "Load a ROM to view the room matrix", 30,
false},
{"dungeon.room_graphics", "Room Graphics", " Room Graphics", ICON_MD_IMAGE,
"Dungeon", "Ctrl+Shift+G", "Load a ROM to view room graphics", 50, false},
{"dungeon.object_editor", "Object Editor", nullptr, ICON_MD_CONSTRUCTION,
"Dungeon", nullptr, nullptr, 60, false},
{"dungeon.sprite_editor", "Sprite Editor", nullptr, ICON_MD_PERSON,
"Dungeon", nullptr, nullptr, 65, false},
{"dungeon.item_editor", "Item Editor", nullptr, ICON_MD_INVENTORY,
"Dungeon", nullptr, nullptr, 66, false},
{"dungeon.palette_editor", "Palette Editor", " Palette Editor",
ICON_MD_PALETTE, "Dungeon", "Ctrl+Shift+P",
"Load a ROM to edit dungeon palettes", 70, false},
// Graphics
{"graphics.sheet_browser_v2", "Sheet Browser", nullptr, ICON_MD_VIEW_LIST,
"Graphics", nullptr, nullptr, 10, true},
{"graphics.pixel_editor", "Pixel Editor", nullptr, ICON_MD_DRAW,
"Graphics", nullptr, nullptr, 20, true},
{"graphics.palette_controls", "Palette Controls", nullptr, ICON_MD_PALETTE,
"Graphics", nullptr, nullptr, 30, false},
{"graphics.link_sprite_editor", "Link Sprite Editor", nullptr,
ICON_MD_PERSON, "Graphics", nullptr, nullptr, 35, false},
{"graphics.polyhedral_editor", "3D Objects", nullptr, ICON_MD_VIEW_IN_AR,
"Graphics", nullptr, nullptr, 38, false},
{"graphics.gfx_group_editor", "Graphics Groups", nullptr,
ICON_MD_VIEW_MODULE, "Graphics", nullptr, nullptr, 39, false},
{"graphics.paletteset_editor", "Palettesets", nullptr,
ICON_MD_COLOR_LENS, "Graphics", nullptr, nullptr, 45, false},
{"graphics.prototype_viewer", "Prototype Viewer", nullptr,
ICON_MD_CONSTRUCTION, "Graphics", nullptr, nullptr, 50, false},
// Palette
{"palette.control_panel", "Palette Controls", " Group Manager",
ICON_MD_PALETTE, "Palette", "Ctrl+Shift+P", "Load a ROM first", 10, false},
{"palette.ow_main", "Overworld Main", " Overworld Main", ICON_MD_LANDSCAPE,
"Palette", "Ctrl+Alt+1", "Load a ROM first", 20, false},
{"palette.ow_animated", "Overworld Animated", " Overworld Animated",
ICON_MD_WATER, "Palette", "Ctrl+Alt+2", "Load a ROM first", 30, false},
{"palette.dungeon_main", "Dungeon Main", " Dungeon Main", ICON_MD_CASTLE,
"Palette", "Ctrl+Alt+3", "Load a ROM first", 40, false},
{"palette.sprites", "Global Sprite Palettes", " SNES Palette",
ICON_MD_PETS, "Palette", "Ctrl+Alt+4", "Load a ROM first", 50, false},
{"palette.sprites_aux1", "Sprites Aux 1", " Sprites Aux 1",
ICON_MD_FILTER_1, "Palette", "Ctrl+Alt+7", "Load a ROM first", 51, false},
{"palette.sprites_aux2", "Sprites Aux 2", " Sprites Aux 2",
ICON_MD_FILTER_2, "Palette", "Ctrl+Alt+8", "Load a ROM first", 52, false},
{"palette.sprites_aux3", "Sprites Aux 3", " Sprites Aux 3",
ICON_MD_FILTER_3, "Palette", "Ctrl+Alt+9", "Load a ROM first", 53, false},
{"palette.equipment", "Equipment Palettes", " Equipment Palettes",
ICON_MD_SHIELD, "Palette", "Ctrl+Alt+5", "Load a ROM first", 60, false},
{"palette.quick_access", "Quick Access", " Color Harmony",
ICON_MD_COLOR_LENS, "Palette", "Ctrl+Alt+Q", "Load a ROM first", 70, false},
{"palette.custom", "Custom Palette", " Palette Editor", ICON_MD_BRUSH,
"Palette", "Ctrl+Alt+C", "Load a ROM first", 80, false},
// Sprite
{"sprite.vanilla_editor", "Vanilla Sprites", nullptr, ICON_MD_SMART_TOY,
"Sprite", nullptr, nullptr, 10, true},
{"sprite.custom_editor", "Custom Sprites", nullptr, ICON_MD_ADD_CIRCLE,
"Sprite", nullptr, nullptr, 20, false},
// Screen
{"screen.dungeon_maps", "Dungeon Maps", " Dungeon Map Editor", ICON_MD_MAP,
"Screen", "Alt+1", "Load a ROM first", 10, false},
{"screen.inventory_menu", "Inventory Menu", " Inventory Menu",
ICON_MD_INVENTORY, "Screen", "Alt+2", "Load a ROM first", 20, false},
{"screen.overworld_map", "Overworld Map", " Overworld Map", ICON_MD_PUBLIC,
"Screen", "Alt+3", "Load a ROM first", 30, false},
{"screen.title_screen", "Title Screen", " Title Screen", ICON_MD_TITLE,
"Screen", "Alt+4", "Load a ROM first", 40, false},
{"screen.naming_screen", "Naming Screen", " Naming Screen", ICON_MD_EDIT,
"Screen", "Alt+5", "Load a ROM first", 50, false},
// Music
{"music.song_browser", "Song Browser", " Song Browser",
ICON_MD_LIBRARY_MUSIC, "Music", "Ctrl+Shift+B", nullptr, 5, false},
{"music.tracker", "Playback Control", " Playback Control",
ICON_MD_PLAY_CIRCLE, "Music", "Ctrl+Shift+M", nullptr, 10, false},
{"music.piano_roll", "Piano Roll", " Piano Roll", ICON_MD_PIANO, "Music",
"Ctrl+Shift+P", nullptr, 15, false},
{"music.instrument_editor", "Instrument Editor", " Instrument Editor",
ICON_MD_SPEAKER, "Music", "Ctrl+Shift+I", nullptr, 20, false},
{"music.sample_editor", "Sample Editor", " Sample Editor", ICON_MD_WAVES,
"Music", "Ctrl+Shift+S", nullptr, 25, false},
{"music.assembly", "Assembly View", " Music Assembly", ICON_MD_CODE,
"Music", "Ctrl+Shift+A", nullptr, 30, false},
{"music.audio_debug", "Audio Debug", " Audio Debug", ICON_MD_BUG_REPORT,
"Music", nullptr, nullptr, 95, false},
{"music.help", "Help", " Music Editor Help", ICON_MD_HELP, "Music", nullptr,
nullptr, 99, false},
// Message
{"message.message_list", "Message List", nullptr, ICON_MD_LIST, "Message",
nullptr, nullptr, 10, false},
{"message.message_editor", "Message Editor", nullptr, ICON_MD_EDIT,
"Message", nullptr, nullptr, 20, false},
{"message.font_atlas", "Font Atlas", nullptr, ICON_MD_FONT_DOWNLOAD,
"Message", nullptr, nullptr, 30, false},
{"message.dictionary", "Dictionary", nullptr, ICON_MD_BOOK, "Message",
nullptr, nullptr, 40, false},
// Assembly
{"assembly.toolbar", "Toolbar", nullptr, ICON_MD_CONSTRUCTION, "Assembly",
nullptr, nullptr, 5, true},
{"assembly.code_editor", "Code Editor", nullptr, ICON_MD_CODE, "Assembly",
nullptr, nullptr, 10, true},
{"assembly.file_browser", "File Browser", nullptr, ICON_MD_FOLDER_OPEN,
"Assembly", nullptr, nullptr, 20, true},
{"assembly.symbols", "Symbols", nullptr, ICON_MD_LIST_ALT, "Assembly",
nullptr, nullptr, 30, false},
{"assembly.build_output", "Build Output", nullptr, ICON_MD_TERMINAL,
"Assembly", nullptr, nullptr, 40, false},
// Emulator + Memory
{"emulator.cpu_debugger", "CPU Debugger", " CPU Debugger",
ICON_MD_BUG_REPORT, "Emulator", nullptr, nullptr, 10, false},
{"emulator.ppu_viewer", "PPU Viewer", " PPU Viewer",
ICON_MD_VIDEOGAME_ASSET, "Emulator", nullptr, nullptr, 20, false},
{"emulator.memory_viewer", "Memory Viewer", " Memory Viewer",
ICON_MD_MEMORY, "Emulator", nullptr, nullptr, 30, false},
{"emulator.breakpoints", "Breakpoints", " Breakpoints", ICON_MD_STOP,
"Emulator", nullptr, nullptr, 40, false},
{"emulator.performance", "Performance", " Performance", ICON_MD_SPEED,
"Emulator", nullptr, nullptr, 50, false},
{"emulator.ai_agent", "AI Agent", " AI Agent", ICON_MD_SMART_TOY,
"Emulator", nullptr, nullptr, 60, false},
{"emulator.save_states", "Save States", " Save States", ICON_MD_SAVE,
"Emulator", nullptr, nullptr, 70, false},
{"emulator.keyboard_config", "Keyboard Config", " Keyboard Config",
ICON_MD_KEYBOARD, "Emulator", nullptr, nullptr, 80, false},
{"emulator.virtual_controller", "Virtual Controller",
" Virtual Controller", ICON_MD_SPORTS_ESPORTS, "Emulator", nullptr, nullptr,
85, false},
{"emulator.apu_debugger", "APU Debugger", " APU Debugger",
ICON_MD_AUDIOTRACK, "Emulator", nullptr, nullptr, 90, false},
{"emulator.audio_mixer", "Audio Mixer", " Audio Mixer", ICON_MD_AUDIO_FILE,
"Emulator", nullptr, nullptr, 100, false},
{"memory.hex_editor", "Hex Editor", nullptr, ICON_MD_MEMORY, "Memory",
nullptr, nullptr, 10, false},
};
void RegisterLabPanels(yaze::editor::PanelManager* panel_manager) {
panel_manager->RegisterSession(kLabSessionId);
panel_manager->SetActiveSession(kLabSessionId);
for (const auto& panel : kLabPanels) {
yaze::editor::PanelDescriptor descriptor;
descriptor.card_id = panel.id;
descriptor.display_name = panel.display_name;
descriptor.window_title = panel.window_title ? panel.window_title : "";
descriptor.icon = panel.icon ? panel.icon : "";
descriptor.category = panel.category ? panel.category : "";
descriptor.shortcut_hint = panel.shortcut ? panel.shortcut : "";
descriptor.disabled_tooltip =
panel.disabled_tooltip ? panel.disabled_tooltip : "";
descriptor.visibility_flag = nullptr;
descriptor.priority = panel.priority;
panel_manager->RegisterPanel(kLabSessionId, descriptor);
if (panel.visible_by_default) {
panel_manager->ShowPanel(kLabSessionId, panel.id);
}
}
}
void DrawDockspace() {
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking |
ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoBringToFrontOnFocus |
ImGuiWindowFlags_NoNavFocus |
ImGuiWindowFlags_NoBackground;
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("LabDockspace", nullptr, window_flags);
ImGui::PopStyleVar(3);
ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f),
ImGuiDockNodeFlags_PassthruCentralNode);
ImGui::End();
}
void DrawLabPanels(const yaze::editor::PanelManager& panel_manager) {
const auto& descriptors = panel_manager.GetAllPanelDescriptors();
for (const auto& [panel_id, descriptor] : descriptors) {
if (descriptor.visibility_flag && !*descriptor.visibility_flag) {
continue;
}
bool open = true;
bool* open_ptr = descriptor.visibility_flag ? descriptor.visibility_flag : &open;
const std::string title = descriptor.GetWindowTitle();
if (ImGui::Begin(title.c_str(), open_ptr)) {
ImGui::Text("Lab panel: %s", descriptor.display_name.c_str());
ImGui::Text("Panel ID: %s", panel_id.c_str());
}
ImGui::End();
}
}
} // namespace
int main(int argc, char** argv) {
(void)argc;
(void)argv;
yaze::util::LogManager::instance().configure(
yaze::util::LogLevel::INFO, "", std::set<std::string>{});
auto window_backend = yaze::platform::WindowBackendFactory::Create(
yaze::platform::WindowBackendFactory::GetDefaultType());
if (!window_backend) {
return EXIT_FAILURE;
}
yaze::platform::WindowConfig config;
config.title = "Yaze Lab";
config.width = 1400;
config.height = 900;
config.resizable = true;
config.high_dpi = false;
if (!window_backend->Initialize(config).ok()) {
return EXIT_FAILURE;
}
auto renderer = yaze::gfx::RendererFactory::Create();
if (!renderer || !window_backend->InitializeRenderer(renderer.get())) {
window_backend->Shutdown();
return EXIT_FAILURE;
}
if (!window_backend->InitializeImGui(renderer.get()).ok()) {
renderer->Shutdown();
window_backend->Shutdown();
return EXIT_FAILURE;
}
yaze::editor::PanelManager panel_manager;
RegisterLabPanels(&panel_manager);
yaze::editor::LayoutManager layout_manager;
layout_manager.SetPanelManager(&panel_manager);
yaze::editor::layout_designer::LayoutDesignerWindow layout_designer;
layout_designer.Initialize(&panel_manager, &layout_manager, nullptr);
layout_designer.Open();
bool running = true;
yaze::platform::WindowEvent event;
while (running && window_backend->IsActive()) {
while (window_backend->PollEvent(event)) {
if (event.type == yaze::platform::WindowEventType::Quit ||
event.type == yaze::platform::WindowEventType::Close) {
running = false;
}
}
window_backend->NewImGuiFrame();
ImGui::NewFrame();
DrawDockspace();
layout_designer.Draw();
DrawLabPanels(panel_manager);
ImGui::Render();
renderer->Clear();
window_backend->RenderImGui(renderer.get());
renderer->Present();
}
window_backend->ShutdownImGui();
renderer->Shutdown();
window_backend->Shutdown();
return EXIT_SUCCESS;
}