Removed core engine infrastructure from warfactoryracine: - Core interfaces: IEngine, IModule, IModuleSystem, IIO, ITaskScheduler, ICoordinationModule - Configuration system: IDataTree, IDataNode, DataTreeFactory - UI system: IUI, IUI_Enums, ImGuiUI (header + implementation) - Resource management: Resource, ResourceRegistry, SerializationRegistry - Serialization: ASerializable, ISerializable - World generation: IWorldGenerationStep (replaced by IWorldGenerationPhase) These components now live in the GroveEngine repository and are included via CMake add_subdirectory(../GroveEngine) for reusability across projects. warfactoryracine remains focused on game-specific logic and content. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
306 lines
12 KiB
C++
306 lines
12 KiB
C++
#include <grove/IUI_Enums.h>
|
|
#include <grove/ImGuiUI.h>
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
|
|
using namespace grove;
|
|
|
|
void showUsage(const char* program_name) {
|
|
std::cout << "Usage: " << program_name << " [options]\n"
|
|
<< "Options:\n"
|
|
<< " --headless Run in headless mode (auto-exit after 3s test)\n"
|
|
<< " --max-frames N Exit after N frames (overrides interactive mode)\n"
|
|
<< " --interactive Run interactively (no auto-exit) [DEFAULT]\n"
|
|
<< " --help Show this help message\n"
|
|
<< "\nDefault behavior: Interactive mode - close window or press Ctrl+C to exit\n";
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
// Parse command line arguments
|
|
bool headless_mode = false;
|
|
bool interactive_mode = true; // DEFAULT: Interactive mode for normal users
|
|
int max_frames = -1; // DEFAULT: No time limit
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
std::string arg = argv[i];
|
|
if (arg == "--headless") {
|
|
headless_mode = true;
|
|
interactive_mode = false; // Override default
|
|
max_frames = 180; // 3 seconds for quick tests
|
|
} else if (arg == "--interactive") {
|
|
interactive_mode = true;
|
|
headless_mode = false;
|
|
max_frames = -1; // No limit
|
|
} else if (arg == "--max-frames" && i + 1 < argc) {
|
|
max_frames = std::atoi(argv[++i]);
|
|
interactive_mode = false; // Override default when explicit limit set
|
|
} else if (arg == "--help") {
|
|
showUsage(argv[0]);
|
|
return 0;
|
|
} else {
|
|
std::cerr << "Unknown option: " << arg << "\n";
|
|
showUsage(argv[0]);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// Show mode info
|
|
if (headless_mode) {
|
|
std::cout << "[MODE] Headless test mode - will exit after " << max_frames << " frames (3s)\n";
|
|
} else if (interactive_mode && max_frames <= 0) {
|
|
std::cout << "[MODE] Interactive mode (DEFAULT) - close window or press Ctrl+C to exit\n";
|
|
std::cout << "[TIP] Use --headless for quick automated tests\n";
|
|
} else {
|
|
std::cout << "[MODE] Timed mode - will exit after " << max_frames << " frames\n";
|
|
std::cout << "[TIP] Use --interactive for manual testing, --headless for quick tests\n";
|
|
}
|
|
|
|
// Create ImGuiUI instance
|
|
ImGuiUI ui;
|
|
|
|
// Initialize with basic config
|
|
ui.initialize({
|
|
{"title", "ImGuiUI Test - Hybrid Sizing System"},
|
|
{"window_size", {{"width", 1400}, {"height", 900}}}
|
|
});
|
|
|
|
ui.info("Testing ImGuiUI implementation with hybrid sizing system");
|
|
|
|
// Test 1: Responsive sidebar - 20% but min 250px
|
|
ui.createDock("sidebar", DockType::TABBED, DockPosition::LEFT, {
|
|
{"size", {{"width", "20%"}, {"height", "90%"}}}, // Target 20% width x 90% height (below toolbar)
|
|
{"min_size", {{"width", 250}, {"height", 500}}}, // Minimum 250px x 500px
|
|
{"max_size", {{"width", 400}, {"height", "95%"}}}, // Maximum 400px x 95% height
|
|
{"resizable", true},
|
|
{"collapsible", true}
|
|
});
|
|
|
|
ui.success("Created responsive sidebar: Target 20%, min 250px, max 400px");
|
|
|
|
// Test 2: Bottom console - 25% height with hybrid constraints
|
|
ui.createDock("console", DockType::DOCK, DockPosition::BOTTOM, {
|
|
{"size", {{"height", "25%"}}}, // Target 25% = 225px
|
|
{"min_size", {{"height", 120}}}, // Minimum 4 lines
|
|
{"max_size", {{"height", "35%"}}}, // Max 35% = 315px
|
|
{"resizable", true}
|
|
});
|
|
|
|
ui.success("Created bottom console: Target 25%, min 120px, max 35%");
|
|
|
|
// Test 3: Economy window in sidebar (FULL HEIGHT)
|
|
ui.showData(DataType::ECONOMY, {
|
|
{"content", {
|
|
{"prices", {{"steel_plate", 5.2}, {"iron_ore", 1.1}, {"copper_ore", 0.8}}},
|
|
{"trends", {{"steel_plate", "+2.1%"}, {"iron_ore", "-0.5%"}, {"copper_ore", "+1.2%"}}},
|
|
{"market_status", "stable"}
|
|
}},
|
|
{"window", {
|
|
{"id", "economy_main"},
|
|
{"title", "💰 Economy Dashboard"},
|
|
{"parent", "sidebar"},
|
|
{"dock", "tab"},
|
|
{"size", {{"width", "90%"}, {"height", "100%"}}}, // 90% sidebar width, FULL height
|
|
{"min_size", {{"width", 200}, {"height", 400}}}, // Minimum for full sidebar
|
|
{"max_size", {{"width", "95%"}, {"height", "100%"}}}// Max 95% sidebar, full height
|
|
}}
|
|
});
|
|
|
|
ui.info("Created economy window: 90% of sidebar width x FULL sidebar height");
|
|
|
|
// Test 3.5: Right sidebar test
|
|
ui.createDock("info_panel", DockType::TABBED, DockPosition::RIGHT, {
|
|
{"size", {{"width", "25%"}, {"height", "90%"}}}, // Target 25% width x 90% height (below toolbar)
|
|
{"min_size", {{"width", 200}, {"height", 500}}}, // Minimum 200px x 500px
|
|
{"max_size", {{"width", 500}, {"height", "95%"}}}, // Maximum 500px x 95% height
|
|
{"resizable", true},
|
|
{"collapsible", true}
|
|
});
|
|
|
|
ui.success("Created right sidebar: Target 25%, min 200px, max 500px");
|
|
|
|
// Test 3.6: Info panel in right sidebar
|
|
ui.showData(DataType::SETTINGS, {
|
|
{"content", {
|
|
{"performance", {{"fps", 60}, {"memory", "156MB"}}},
|
|
{"debug", {{"entities", 2847}, {"chunks_loaded", 12}}}
|
|
}},
|
|
{"window", {
|
|
{"id", "info_panel_main"},
|
|
{"title", "📊 Info Panel"},
|
|
{"parent", "info_panel"},
|
|
{"dock", "tab"},
|
|
{"size", {{"width", "95%"}, {"height", "100%"}}}, // 95% right sidebar, full height
|
|
{"min_size", {{"width", 180}, {"height", 300}}},
|
|
{"max_size", {{"width", "100%"}, {"height", "100%"}}}
|
|
}}
|
|
});
|
|
|
|
ui.info("Created info panel: 95% of right sidebar width x FULL height");
|
|
|
|
// Test 3.7: Top toolbar test
|
|
ui.createDock("toolbar", DockType::DOCK, DockPosition::TOP, {
|
|
{"size", {{"width", "100%"}, {"height", "8%"}}}, // FULL width x 8% height
|
|
{"min_size", {{"width", 800}, {"height", 50}}}, // Minimum 800px x 50px
|
|
{"max_size", {{"width", "100%"}, {"height", 120}}}, // FULL width x max 120px
|
|
{"resizable", true}
|
|
});
|
|
|
|
ui.success("Created top toolbar: Target 8%, min 50px, max 120px");
|
|
|
|
// Test 3.8: Toolbar content
|
|
ui.showData(DataType::CUSTOM, {
|
|
{"content", {
|
|
{"buttons", {"New", "Save", "Load", "Export"}},
|
|
{"current_tool", "Select"}
|
|
}},
|
|
{"window", {
|
|
{"id", "toolbar_main"},
|
|
{"title", "🛠️ Toolbar"},
|
|
{"parent", "toolbar"},
|
|
{"dock", "tab"},
|
|
{"size", {{"width", "100%"}, {"height", "90%"}}}, // Full width, 90% toolbar height
|
|
{"min_size", {{"width", 400}, {"height", 40}}},
|
|
{"max_size", {{"width", "100%"}, {"height", "95%"}}}
|
|
}}
|
|
});
|
|
|
|
ui.info("Created toolbar: 100% width x 90% of toolbar height");
|
|
|
|
// Test 4: Map window
|
|
ui.showData(DataType::MAP, {
|
|
{"content", {
|
|
{"current_chunk", {{"x", 0}, {"y", 0}}},
|
|
{"tiles", {{"iron", 25}, {"copper", 15}, {"coal", 10}}}
|
|
}},
|
|
{"window", {
|
|
{"id", "map_main"},
|
|
{"title", "🗺️ Global Map"},
|
|
{"size", {{"width", "50%"}, {"height", "60%"}}}, // 50% x 60% of screen
|
|
{"min_size", {{"width", 400}, {"height", 300}}}, // Minimum for visibility
|
|
{"max_size", {{"width", 800}, {"height", 600}}} // Don't dominate
|
|
}}
|
|
});
|
|
|
|
ui.info("Created map window: 50% x 60% of screen with 400x300-800x600 constraints");
|
|
|
|
// Test 5: Settings dialog - floating with hybrid sizing
|
|
ui.showData(DataType::SETTINGS, {
|
|
{"content", {
|
|
{"graphics", {{"resolution", "1400x900"}, {"fullscreen", false}, {"vsync", true}}},
|
|
{"audio", {{"master_volume", 0.8}, {"effects_volume", 0.7}}},
|
|
{"controls", {{"mouse_sensitivity", 1.2}}}
|
|
}},
|
|
{"window", {
|
|
{"id", "settings_dialog"},
|
|
{"title", "⚙️ Settings"},
|
|
{"floating", true},
|
|
{"size", {{"width", "30%"}, {"height", "40%"}}}, // 30% x 40% of screen
|
|
{"min_size", {{"width", 400}, {"height", 300}}}, // Usable dialog size
|
|
{"max_size", {{"width", 600}, {"height", 500}}} // Don't dominate
|
|
}}
|
|
});
|
|
|
|
ui.info("Created settings dialog: Floating 30% x 40% with 400x300-600x500 constraints");
|
|
|
|
// Set up callbacks for testing
|
|
ui.onRequest(RequestType::GET_PRICES, [&](const json& req) {
|
|
ui.info("📈 Price update requested - would fetch from backend");
|
|
|
|
// Simulate price update
|
|
ui.showData(DataType::ECONOMY, {
|
|
{"content", {
|
|
{"prices", {{"steel_plate", 5.7}, {"iron_ore", 1.0}, {"copper_ore", 0.9}}},
|
|
{"trends", {{"steel_plate", "+9.6%"}, {"iron_ore", "-9.1%"}, {"copper_ore", "+12.5%"}}},
|
|
{"market_status", "volatile"}
|
|
}},
|
|
{"window", {
|
|
{"id", "economy_main"}
|
|
}}
|
|
});
|
|
});
|
|
|
|
ui.onRequest(RequestType::GET_CHUNK, [&](const json& req) {
|
|
ui.info("🗺️ Map chunk requested: " + req.dump());
|
|
|
|
// Simulate chunk update
|
|
ui.showData(DataType::MAP, {
|
|
{"content", {
|
|
{"current_chunk", {{"x", 1}, {"y", 0}}},
|
|
{"tiles", {{"iron", 30}, {"copper", 8}, {"stone", 12}}}
|
|
}},
|
|
{"window", {
|
|
{"id", "map_main"}
|
|
}}
|
|
});
|
|
});
|
|
|
|
ui.onRequestCustom("console_command", [&](const json& req) {
|
|
std::string command = req.value("command", "");
|
|
ui.info("💻 Console command: " + command);
|
|
|
|
if (command == "test_resize") {
|
|
ui.info("🔄 Testing window resize behavior...");
|
|
// All percentage-based sizes would recalculate automatically
|
|
} else if (command == "show_performance") {
|
|
ui.showData(DataType::PERFORMANCE, {
|
|
{"content", {
|
|
{"fps", 60},
|
|
{"frame_time", "16.7ms"},
|
|
{"memory_usage", "156MB"},
|
|
{"entities", 2847}
|
|
}},
|
|
{"window", {
|
|
{"id", "performance_monitor"},
|
|
{"title", "📊 Performance Monitor"},
|
|
{"size", {{"width", 300}, {"height", "25%"}}}, // 300px x 25% height
|
|
{"min_size", {{"width", 250}, {"height", 200}}},
|
|
{"floating", true}
|
|
}}
|
|
});
|
|
}
|
|
});
|
|
|
|
ui.success("All callbacks configured - UI ready for testing!");
|
|
ui.info("Commands: 'test_resize', 'show_performance'");
|
|
ui.info("Try resizing the window to see responsive percentage behavior");
|
|
|
|
// Main loop with configurable timeout
|
|
int frame = 0;
|
|
bool should_exit = false;
|
|
|
|
while (ui.update() && !should_exit) {
|
|
frame++;
|
|
|
|
// Test automatic percentage recalculation
|
|
if (frame == 60) { // 1s at 60fps
|
|
ui.debug("🔄 Simulating window resize - percentages recalculate automatically");
|
|
}
|
|
|
|
if (frame % 60 == 0) { // Every second
|
|
ui.info("Frame " + std::to_string(frame) + " - Docking system operational");
|
|
}
|
|
|
|
// Headless mode: quick test and exit
|
|
if (headless_mode && frame == 120) { // 2s at 60fps
|
|
ui.success("✅ Headless docking test completed successfully!");
|
|
should_exit = true;
|
|
}
|
|
|
|
// Standard/Interactive mode: check frame limit
|
|
if (max_frames > 0 && frame >= max_frames) {
|
|
ui.info("🕐 Auto-exit after " + std::to_string(max_frames) + " frames");
|
|
should_exit = true;
|
|
}
|
|
|
|
// Interactive mode message
|
|
if (interactive_mode && frame == 180) { // Show tip after 3 seconds
|
|
ui.info("💡 Interactive mode: Close window or press Ctrl+C to exit");
|
|
}
|
|
}
|
|
|
|
ui.info("Exited at frame " + std::to_string(frame));
|
|
|
|
ui.info("Shutting down ImGuiUI test");
|
|
ui.shutdown();
|
|
return 0;
|
|
} |