#include #include #include #include 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; }